diff --git a/src/cisco_lib/CompilerDriver_iosacl_run.cpp b/src/cisco_lib/CompilerDriver_iosacl_run.cpp index 30f908148..e68200405 100644 --- a/src/cisco_lib/CompilerDriver_iosacl_run.cpp +++ b/src/cisco_lib/CompilerDriver_iosacl_run.cpp @@ -119,13 +119,9 @@ QString CompilerDriver_iosacl::run(const std::string &cluster_id, const std::string &single_rule_id) { Cluster *cluster = NULL; - if (!cluster_id.empty()) - cluster = Cluster::cast( - objdb->findInIndex(objdb->getIntId(cluster_id))); + Firewall *fw = NULL; - Firewall *fw = Firewall::cast( - objdb->findInIndex(objdb->getIntId(firewall_id))); - assert(fw); + getFirewallAndClusterObjects(cluster_id, firewall_id, &cluster, &fw); try { @@ -181,6 +177,13 @@ QString CompilerDriver_iosacl::run(const std::string &cluster_id, list all_policies = fw->getByType(Policy::TYPENAME); + // assign unique rule ids that later will be used to generate + // chain names. This should be done after calls to + // findImportedRuleSets() + // NB: these ids are not used by this compiler + + assignUniqueRuleIds(all_policies); + vector ipv4_6_runs; if (!single_rule_compile_on) diff --git a/src/cisco_lib/CompilerDriver_pix_run.cpp b/src/cisco_lib/CompilerDriver_pix_run.cpp index ec60ed4e9..cbc0bcf2a 100644 --- a/src/cisco_lib/CompilerDriver_pix_run.cpp +++ b/src/cisco_lib/CompilerDriver_pix_run.cpp @@ -165,11 +165,9 @@ QString CompilerDriver_pix::run(const std::string &cluster_id, const std::string &single_rule_id) { Cluster *cluster = NULL; - if (!cluster_id.empty()) - cluster = Cluster::cast(objdb->findInIndex(objdb->getIntId(cluster_id))); + Firewall *fw = NULL; - Firewall *fw = Firewall::cast(objdb->findInIndex(objdb->getIntId(firewall_id))); - assert(fw); + getFirewallAndClusterObjects(cluster_id, firewall_id, &cluster, &fw); // Copy rules from the cluster object populateClusterElements(cluster, fw); @@ -386,6 +384,8 @@ QString CompilerDriver_pix::run(const std::string &cluster_id, RuleSet *nat = RuleSet::cast(fw->getFirstByType(NAT::TYPENAME)); if (nat) { + nat->assignUniqueRuleIds(); + n->setNamedObjectsManager(&named_objects_manager); n->setSourceRuleSet(nat); n->setRuleSetName(nat->getName()); @@ -419,6 +419,8 @@ QString CompilerDriver_pix::run(const std::string &cluster_id, RuleSet *policy = RuleSet::cast(fw->getFirstByType(Policy::TYPENAME)); if (policy) { + policy->assignUniqueRuleIds(); + c->setNamedObjectsManager(&named_objects_manager); c->setSourceRuleSet(policy); c->setRuleSetName(policy->getName()); @@ -452,6 +454,8 @@ QString CompilerDriver_pix::run(const std::string &cluster_id, RuleSet *routing = RuleSet::cast(fw->getFirstByType(Routing::TYPENAME)); if (routing) { + routing->assignUniqueRuleIds(); + r->setNamedObjectsManager(&named_objects_manager); r->setSourceRuleSet(routing); r->setRuleSetName(routing->getName()); diff --git a/src/cisco_lib/CompilerDriver_procurve_acl_run.cpp b/src/cisco_lib/CompilerDriver_procurve_acl_run.cpp index 713cf6e8a..0b08c8536 100644 --- a/src/cisco_lib/CompilerDriver_procurve_acl_run.cpp +++ b/src/cisco_lib/CompilerDriver_procurve_acl_run.cpp @@ -115,13 +115,9 @@ QString CompilerDriver_procurve_acl::run(const std::string &cluster_id, const std::string &single_rule_id) { Cluster *cluster = NULL; - if (!cluster_id.empty()) - cluster = Cluster::cast( - objdb->findInIndex(objdb->getIntId(cluster_id))); + Firewall *fw = NULL; - Firewall *fw = Firewall::cast( - objdb->findInIndex(objdb->getIntId(firewall_id))); - assert(fw); + getFirewallAndClusterObjects(cluster_id, firewall_id, &cluster, &fw); try { @@ -169,6 +165,13 @@ QString CompilerDriver_procurve_acl::run(const std::string &cluster_id, list all_policies = fw->getByType(Policy::TYPENAME); + // assign unique rule ids that later will be used to generate + // chain names. This should be done after calls to + // findImportedRuleSets() + // NB: these ids are not used by this compiler + + assignUniqueRuleIds(all_policies); + vector ipv4_6_runs; if (!single_rule_compile_on) diff --git a/src/compiler_lib/AutomaticRules.cpp b/src/compiler_lib/AutomaticRules.cpp new file mode 100644 index 000000000..4f82a33f2 --- /dev/null +++ b/src/compiler_lib/AutomaticRules.cpp @@ -0,0 +1,131 @@ +/* + + Firewall Builder + + Copyright (C) 2011 NetCitadel, LLC + + Author: Vadim Kurland vadim@fwbuilder.org + + This program is free software which we release under the GNU General Public + License. You may redistribute and/or modify this program under the terms + of that 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. + + To get a copy of the GNU General Public License, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "AutomaticRules.h" + +#include "fwbuilder/Address.h" +#include "fwbuilder/FWException.h" +#include "fwbuilder/FWObjectDatabase.h" +#include "fwbuilder/Firewall.h" +#include "fwbuilder/Interface.h" +#include "fwbuilder/Library.h" +#include "fwbuilder/Resources.h" +#include "fwbuilder/Rule.h" +#include "fwbuilder/RuleElement.h" +#include "fwbuilder/Policy.h" + + +using namespace fwcompiler; +using namespace libfwbuilder; +using namespace std; + + +AutomaticRules::AutomaticRules(Firewall *fw, Library *persistent_objects) +{ + this->fw = fw; + this->persistent_objects = persistent_objects; + ruleset = NULL; + + list all_policies = fw->getByType(Policy::TYPENAME); + for (FWObject::iterator it=all_policies.begin(); it!=all_policies.end(); ++it) + { + Policy *policy = Policy::cast(*it); + + FWOptions *rulesetopts = policy->getOptionsObject(); + if (rulesetopts->getBool("mangle_only_rule_set")) continue; + + if (policy->isTop()) + { + ruleset = policy; + break; + } + } +} + +PolicyRule* AutomaticRules::addMgmtRule( + Address* src, + Address* dst, + Service* service, + Interface* iface, + const PolicyRule::Direction direction, + const PolicyRule::Action action, + const string &label, + bool related) +{ + if (ruleset == NULL) return NULL; + + /* Insert PolicyRules at top so they do not get shadowed by other + * rules. Call insertRuleAtTop() with hidden_rule argument true to + * make sure this rule gets negative position number and does not + * shift positions of other rules. See ticket #16. Also, hidden + * rules are not considered for shadowing. + */ + + PolicyRule* rule = PolicyRule::cast(ruleset->insertRuleAtTop(true)); + assert(rule != NULL); + + ostringstream str; + str << rule->getPosition() << " " << label << " (automatic)" ; + rule->setLabel(str.str()); + + FWObject *re; + re = rule->getSrc(); assert(re!=NULL); + RuleElementSrc::cast(re)->reset(); + if(src != NULL) + re->addRef(src); + + re = rule->getDst(); assert(re!=NULL); + RuleElementDst::cast(re)->reset(); + if(dst != NULL) + re->addRef(dst); + + re = rule->getSrv(); assert(re!=NULL); + RuleElementSrv::cast(re)->reset(); + if(service != NULL) + re->addRef(service); + + re = rule->getWhen(); assert(re!=NULL); + RuleElementInterval::cast(re)->reset(); + + re = rule->getItf(); assert(re!=NULL); + RuleElementItf::cast(re)->reset(); + if(iface != NULL) + { + re->addRef(iface); +// rule->setInterfaceId(iface->getId()); + } + + rule->add(ruleset->getRoot()->create(PolicyRuleOptions::TYPENAME)); + rule->setLogging(false); + rule->enable(); + rule->setAction(action); + rule->setDirection(direction); + // Use firewall object ID to generate uique ID for this management rule + // to make it stable across different runs of the compiler + rule->setUniqueId( + ruleset->getRoot()->getPredictableId( + FWObjectDatabase::getStringId(fw->getId()) + "." + )); + + return rule; +} diff --git a/src/compiler_lib/AutomaticRules.h b/src/compiler_lib/AutomaticRules.h new file mode 100644 index 000000000..16a2249e4 --- /dev/null +++ b/src/compiler_lib/AutomaticRules.h @@ -0,0 +1,73 @@ +/* + + Firewall Builder + + Copyright (C) 2011 NetCitadel, LLC + + Author: Vadim Kurland vadim@fwbuilder.org + + This program is free software which we release under the GNU General Public + License. You may redistribute and/or modify this program under the terms + of that 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. + + To get a copy of the GNU General Public License, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#ifndef __AUTOMATICRULES_HH__ +#define __AUTOMATICRULES_HH__ + +#include "fwbuilder/Rule.h" + +#include +#include + + +namespace libfwbuilder +{ + class Address; + class Firewall; + class Interface; + class Library; + class Service; +}; + +namespace fwcompiler +{ + +class AutomaticRules +{ + +protected: + libfwbuilder::Firewall *fw; + libfwbuilder::RuleSet *ruleset; + libfwbuilder::Library *persistent_objects; + +public: + + AutomaticRules(libfwbuilder::Firewall *fw, + libfwbuilder::Library *persistent_objects); + + virtual libfwbuilder::PolicyRule* addMgmtRule( + libfwbuilder::Address* src, + libfwbuilder::Address* dst, + libfwbuilder::Service* service, + libfwbuilder::Interface* iface, + const libfwbuilder::PolicyRule::Direction direction, + const libfwbuilder::PolicyRule::Action action, + const std::string &label, + bool related = false); + +}; + +}; + + +#endif diff --git a/src/compiler_lib/CompilerDriver.cpp b/src/compiler_lib/CompilerDriver.cpp index 878a57ec7..9280009ca 100644 --- a/src/compiler_lib/CompilerDriver.cpp +++ b/src/compiler_lib/CompilerDriver.cpp @@ -92,10 +92,19 @@ CompilerDriver::CompilerDriver(FWObjectDatabase *db) : BaseCompiler() ipv4_run = true; ipv6_run = true; fw_by_id = false; + objdb = new FWObjectDatabase(*db); + + //objdb = db; + persistent_objects = new Library(); persistent_objects->setName("Persistent Objects"); objdb->add(persistent_objects); + + workspace = new Library(); + workspace->setName("Workspace"); + objdb->add(workspace); + prolog_done = false; epilog_done = false; have_filter = false; @@ -105,6 +114,28 @@ CompilerDriver::CompilerDriver(FWObjectDatabase *db) : BaseCompiler() CompilerDriver::~CompilerDriver() { + if (persistent_objects->getParent() == NULL) + delete persistent_objects; + else + { + if (persistent_objects->getParent() == objdb) + { + objdb->remove(persistent_objects, false); + delete persistent_objects; + } + } + + if (workspace->getParent() == NULL) + delete workspace; + else + { + if (workspace->getParent() == objdb) + { + objdb->remove(workspace, false); + delete workspace; + } + } + delete objdb; } @@ -689,9 +720,12 @@ void CompilerDriver::findImportedRuleSets(Firewall *fw, if (branch_ruleset->isChildOf(fw)) continue; - list::iterator it = std::find(imported_policies.begin(), - imported_policies.end(), - branch_ruleset); + list::iterator it = + std::find( + imported_policies.begin(), + imported_policies.end(), + branch_ruleset); + if (it != imported_policies.end()) continue; // Additional check: the rule set may be child of a @@ -707,6 +741,7 @@ void CompilerDriver::findImportedRuleSets(Firewall *fw, } } } + if (imported_policies.size() > 0) all_policies.insert(all_policies.end(), imported_policies.begin(), imported_policies.end()); @@ -738,6 +773,11 @@ void CompilerDriver::_findImportedRuleSetsRecursively( } } +void CompilerDriver::assignUniqueRuleIds(list &all_rulesets) +{ + for_each(all_rulesets.begin(), all_rulesets.end(), + RuleSet::UniqueRuleIdsSetter()); +} QString CompilerDriver::run(const std::string&, const std::string&, const std::string&) { @@ -859,8 +899,10 @@ void CompilerDriver::mergeRuleSets(Cluster *cluster, Firewall *fw, { FWObject *ruleset = *p; - FWObject::iterator i = std::find_if(fw->begin(), fw->end(), - FWObjectNameEQPredicate(ruleset->getName())); + FWObject::iterator i = std::find_if( + fw->begin(), fw->end(), + FWObjectNameEQPredicate(ruleset->getName())); + if (i!=fw->end() && (*i)->getTypeName() == type) { FWObject *fw_ruleset = *i; @@ -929,6 +971,20 @@ void CompilerDriver::populateClusterElements(Cluster *cluster, Firewall *fw) { if (cluster==NULL) return; +#ifdef DEBUG_CLUSTER_INTERFACES + cerr << "CompilerDriver::populateClusterElements " << endl; + + cerr << cluster->getPath(false, true) << endl; + list cl_interfaces = cluster->getByTypeDeep(Interface::TYPENAME); + cerr << cl_interfaces.size() << " interface" << endl; + cluster->dump(false, true); + + cerr << fw->getPath(false, true) << endl; + list fw_interfaces = fw->getByTypeDeep(Interface::TYPENAME); + cerr << fw_interfaces.size() << " interface" << endl; + fw->dump(false, true); +#endif + // int addedPolicies = 0; set state_sync_types; @@ -1189,3 +1245,51 @@ QString CompilerDriver::formSingleRuleCompileOutput(const QString &generated_cod return res; } +void CompilerDriver::getFirewallAndClusterObjects(const string &cluster_id, + const string &firewall_id, + Cluster **cl, + Firewall **fw) +{ + if (!cluster_id.empty()) + { + Cluster *orig_cluster = Cluster::cast( + objdb->findInIndex(objdb->getIntId(cluster_id))); + +#ifdef WORK_ON_COPIES + *cl = objdb->createCluster(); + workspace->add(*cl); + (*cl)->duplicate(orig_cluster); +#else + + *cl = orig_cluster; + +#endif + + } + + Firewall *orig_fw = Firewall::cast( + objdb->findInIndex(objdb->getIntId(firewall_id))); + assert(orig_fw); + +#ifdef WORK_ON_COPIES + + *fw = objdb->createFirewall(); + workspace->add(*fw); + (*fw)->duplicate(orig_fw); + + if (*cl != NULL) + { + const map &id_map = (*fw)->getIDMappingTable(); + map::const_iterator it; + for (it=id_map.begin(); it!=id_map.end(); ++it) + (*cl)->replaceRef(it->first, it->second); + } +#else + + *fw = orig_fw; + +#endif + +} + + diff --git a/src/compiler_lib/CompilerDriver.h b/src/compiler_lib/CompilerDriver.h index 4f9dc2986..4fab0690f 100644 --- a/src/compiler_lib/CompilerDriver.h +++ b/src/compiler_lib/CompilerDriver.h @@ -133,6 +133,7 @@ protected: libfwbuilder::FWObjectDatabase *objdb; libfwbuilder::Library *persistent_objects; + libfwbuilder::Library *workspace; void determineOutputFileNames(libfwbuilder::Cluster *cluster, libfwbuilder::Firewall *current_fw, @@ -251,9 +252,16 @@ public: */ virtual libfwbuilder::Firewall* locateObject(); + void getFirewallAndClusterObjects(const std::string &cluster_id, + const std::string &fw_id, + libfwbuilder::Cluster **cl, + libfwbuilder::Firewall **fw); + void findImportedRuleSets(libfwbuilder::Firewall *fw, std::list &all_policies); + void assignUniqueRuleIds(std::list &all_policies); + virtual bool prepare(const QStringList &args); virtual void compile(); virtual QMap compileSingleRule(const std::string &rule_id); diff --git a/src/compiler_lib/CompilerDriver_compile.cpp b/src/compiler_lib/CompilerDriver_compile.cpp index 0a3185d3b..f56f5f1a5 100644 --- a/src/compiler_lib/CompilerDriver_compile.cpp +++ b/src/compiler_lib/CompilerDriver_compile.cpp @@ -31,11 +31,12 @@ #include "CompilerDriver.h" -#include "fwbuilder/FWObjectDatabase.h" -#include "fwbuilder/FWException.h" #include "fwbuilder/Cluster.h" +#include "fwbuilder/FWException.h" +#include "fwbuilder/FWObjectDatabase.h" #include "fwbuilder/Firewall.h" #include "fwbuilder/Interface.h" +#include "fwbuilder/Library.h" #include "fwbuilder/Rule.h" #include "fwcompiler/Compiler.h" @@ -144,8 +145,15 @@ QMap CompilerDriver::compileSingleRule(const string &rule_id) if (cluster) { commonChecks(cluster); + list members; Cluster::cast(cluster)->getMembersList(members); + + // this copy of CompilerDriver is not going to do any useful work and + // does not need these. + objdb->remove(persistent_objects, false); + objdb->remove(workspace, false); + for (list::iterator it=members.begin(); it!=members.end(); ++it) { CompilerDriver *cl_driver = clone(); diff --git a/src/compiler_lib/compiler_lib.pro b/src/compiler_lib/compiler_lib.pro index 9d8ccd36b..ec33db6ee 100644 --- a/src/compiler_lib/compiler_lib.pro +++ b/src/compiler_lib/compiler_lib.pro @@ -19,7 +19,8 @@ SOURCES = CompilerDriver.cpp \ iosInterfaces.cpp \ procurveInterfaces.cpp \ pixInterfaces.cpp \ - interfacePropertiesObjectFactory.cpp + interfacePropertiesObjectFactory.cpp \ + AutomaticRules.cpp HEADERS = ../../config.h \ CompilerDriver.h \ @@ -31,7 +32,8 @@ HEADERS = ../../config.h \ iosInterfaces.h \ procurveInterfaces.h \ pixInterfaces.h \ - interfacePropertiesObjectFactory.h + interfacePropertiesObjectFactory.h \ + AutomaticRules.h INCLUDEPATH += ../libfwbuilder/src diff --git a/src/iosacl/iosacl.cpp b/src/iosacl/iosacl.cpp index 4cae9049c..9062d26ab 100644 --- a/src/iosacl/iosacl.cpp +++ b/src/iosacl/iosacl.cpp @@ -153,16 +153,20 @@ int main(int argc, char **argv) FWObject *slib = objdb->getById(FWObjectDatabase::STANDARD_LIB_ID); if (slib && slib->isReadOnly()) slib->setReadOnly(false); - CompilerDriver_iosacl driver(objdb); - if (!driver.prepare(args)) + CompilerDriver_iosacl *driver = new CompilerDriver_iosacl(objdb); + if (!driver->prepare(args)) { usage(argv[0]); exit(1); } - driver.compile(); + driver->compile(); + int ret = (driver->getStatus() == BaseCompiler::FWCOMPILER_SUCCESS) ? 0 : 1; + + delete driver; delete objdb; - return (driver.getStatus() == BaseCompiler::FWCOMPILER_SUCCESS) ? 0 : 1; + + return ret; } catch(libfwbuilder::FWException &ex) { diff --git a/src/ipf/ipf.cpp b/src/ipf/ipf.cpp index de0c30ecd..bca7a2eba 100644 --- a/src/ipf/ipf.cpp +++ b/src/ipf/ipf.cpp @@ -167,15 +167,19 @@ int main(int argc, char **argv) FWObject *slib = objdb->getById(FWObjectDatabase::STANDARD_LIB_ID); if (slib && slib->isReadOnly()) slib->setReadOnly(false); - CompilerDriver_ipf driver(objdb); - if (!driver.prepare(args)) + CompilerDriver_ipf *driver = new CompilerDriver_ipf(objdb); + if (!driver->prepare(args)) { usage(argv[0]); exit(1); } - driver.compile(); + driver->compile(); + int ret = (driver->getStatus() == BaseCompiler::FWCOMPILER_SUCCESS) ? 0 : 1; + + delete driver; delete objdb; - return (driver.getStatus() == BaseCompiler::FWCOMPILER_SUCCESS) ? 0 : 1; + + return ret; } catch(const FWException &ex) { cerr << ex.toString() << endl; diff --git a/src/ipfw/ipfw.cpp b/src/ipfw/ipfw.cpp index 593b0fc88..0a54a77da 100644 --- a/src/ipfw/ipfw.cpp +++ b/src/ipfw/ipfw.cpp @@ -163,15 +163,19 @@ int main(int argc, char **argv) FWObject *slib = objdb->getById(FWObjectDatabase::STANDARD_LIB_ID); if (slib && slib->isReadOnly()) slib->setReadOnly(false); - CompilerDriver_ipfw driver(objdb); - if (!driver.prepare(args)) + CompilerDriver_ipfw *driver = new CompilerDriver_ipfw(objdb); + if (!driver->prepare(args)) { usage(argv[0]); exit(1); } - driver.compile(); + driver->compile(); + int ret = (driver->getStatus() == BaseCompiler::FWCOMPILER_SUCCESS) ? 0 : 1; + + delete driver; delete objdb; - return (driver.getStatus() == BaseCompiler::FWCOMPILER_SUCCESS) ? 0 : 1; + + return ret; } catch(const FWException &ex) { diff --git a/src/ipt/ipt.cpp b/src/ipt/ipt.cpp index 34fee9ae5..e4ce3f506 100644 --- a/src/ipt/ipt.cpp +++ b/src/ipt/ipt.cpp @@ -144,16 +144,19 @@ int main(int argc, char **argv) FWObject *slib = objdb->findInIndex(FWObjectDatabase::STANDARD_LIB_ID); if (slib && slib->isReadOnly()) slib->setReadOnly(false); - CompilerDriver_ipt driver(objdb); - if (!driver.prepare(args)) + CompilerDriver_ipt *driver = new CompilerDriver_ipt(objdb); + if (!driver->prepare(args)) { usage(argv[0]); exit(1); } - driver.compile(); + driver->compile(); + int ret = (driver->getStatus() == BaseCompiler::FWCOMPILER_SUCCESS) ? 0 : 1; + + delete driver; delete objdb; - return (driver.getStatus() == BaseCompiler::FWCOMPILER_SUCCESS) ? 0 : 1; + return ret; } catch(const FWException &ex) { diff --git a/src/iptlib/AutomaticRules_ipt.cpp b/src/iptlib/AutomaticRules_ipt.cpp new file mode 100644 index 000000000..7916617dc --- /dev/null +++ b/src/iptlib/AutomaticRules_ipt.cpp @@ -0,0 +1,472 @@ +/* + + Firewall Builder + + Copyright (C) 2011 NetCitadel, LLC + + Author: Vadim Kurland vadim@fwbuilder.org + + This program is free software which we release under the GNU General Public + License. You may redistribute and/or modify this program under the terms + of that 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. + + To get a copy of the GNU General Public License, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "AutomaticRules_ipt.h" + +#include "fwbuilder/Address.h" +#include "fwbuilder/FWException.h" +#include "fwbuilder/FWObjectDatabase.h" +#include "fwbuilder/Firewall.h" +#include "fwbuilder/Interface.h" +#include "fwbuilder/Library.h" +#include "fwbuilder/Resources.h" +#include "fwbuilder/Rule.h" +#include "fwbuilder/RuleElement.h" +#include "fwbuilder/Policy.h" +#include "fwbuilder/StateSyncClusterGroup.h" +#include "fwbuilder/UDPService.h" +#include "fwbuilder/FailoverClusterGroup.h" +#include "fwbuilder/IPService.h" + +#include + + +using namespace fwcompiler; +using namespace libfwbuilder; +using namespace std; + + + +PolicyRule* AutomaticRules_ipt::addMgmtRule( + Address* src, Address* dst, Service* service, Interface* iface, + const PolicyRule::Direction direction, + const PolicyRule::Action action, + const string &label, + bool related) +{ + PolicyRule *rule = AutomaticRules::addMgmtRule(src, dst, service, + iface, direction, action, + label); + + FWOptions *ruleopt = rule->getOptionsObject(); assert(ruleopt!=NULL); + if (related) + { + ruleopt->setBool("stateless", false); + ruleopt->setBool("accept_established", true); + } else + { + ruleopt->setBool("stateless", true); + } + ruleopt->setBool("firewall_is_part_of_any_and_networks", true); + + return rule; +} + +void AutomaticRules_ipt::addConntrackRule() +{ + FWOptions* options = fw->getOptionsObject(); + string conntrack_iface_name = options->getStr("state_sync_interface"); + if (conntrack_iface_name.empty()) + { + /* CONNTRACK not active, nothing left to do */ + return; + } + + string conntrack_group_id = options->getStr("state_sync_group_id"); + StateSyncClusterGroup *state_sync_group = + StateSyncClusterGroup::cast( + ruleset->getRoot()->findInIndex( + FWObjectDatabase::getIntId(conntrack_group_id))); + + Resources *os_res = Resources::os_res[fw->getStr("host_OS")]; + assert(os_res != NULL); + + string default_address = + os_res->getResourceStr("/FWBuilderResources/Target/protocols/conntrack/default_address"); + string default_port = + os_res->getResourceStr("/FWBuilderResources/Target/protocols/conntrack/default_port"); + + bool ucast = state_sync_group->getOptionsObject()->getBool("conntrack_unicast"); + string addr = state_sync_group->getOptionsObject()->getStr("conntrack_address"); + if (addr.empty()) addr = default_address; + + try + { + InetAddr(addr); + } catch (FWException &ex) + { + try + { + InetAddr(AF_INET6, addr); + } catch (FWException &ex) + { + throw FWException(string("Invalid IP address for conntrack: ") + addr); + } + } + + string port = state_sync_group->getOptionsObject()->getStr("conntrack_port"); + if (port.empty()) port = default_port; + + /* Add CONNTRACK-Address to database */ + Address *conntrack_dst = Address::cast(ruleset->getRoot()->create(IPv4::TYPENAME)); + conntrack_dst->setName("CONNTRACK-Address"); + conntrack_dst->setAddress(InetAddr(addr)); + // Why the whole multicast adress range ? + //conntrack_dst->setNetmask(InetAddr("240.0.0.0")); + conntrack_dst->setComment("CONNTRACK Multicast Address"); + persistent_objects->add(conntrack_dst); + + UDPService *conntrack_srv = UDPService::cast(ruleset->getRoot()->create(UDPService::TYPENAME)); + conntrack_srv->setName("CONNTRACK-UDP"); + conntrack_srv->setDstRangeStart(atoi(port.c_str())); + conntrack_srv->setDstRangeEnd(atoi(port.c_str())); + conntrack_srv->setComment("CONNTRACK UDP port"); + persistent_objects->add(conntrack_srv); + + /* Find conntrack interface */ + Interface* conntrack_iface = Interface::cast(fw->findObjectByName(Interface::TYPENAME, conntrack_iface_name)); + + if (conntrack_iface == NULL) + { + throw FWException( + "Unable to get CONNTRACK interface ("+ conntrack_iface_name +")"); + } + + /* Add automatic rules for CONNTRACK */ + if (ucast) + { + Interface *fw_iface = NULL; + list other_interfaces; + for (FWObjectTypedChildIterator it = + state_sync_group->findByType(FWObjectReference::TYPENAME); + it != it.end(); ++it) + { + Interface *iface = + Interface::cast(FWObjectReference::getObject(*it)); + assert(iface); + if (iface->isChildOf(fw)) + { + fw_iface = iface; + } else + { + other_interfaces.push_back(iface); + } + } + + for (list::iterator it=other_interfaces.begin(); it!=other_interfaces.end(); ++it) + { + Interface *other_iface = *it; + + addMgmtRule(other_iface, + fw, + conntrack_srv, + fw_iface, + PolicyRule::Inbound, + PolicyRule::Accept, + "CONNTRACK"); + addMgmtRule(fw, + other_iface, + conntrack_srv, + fw_iface, + PolicyRule::Outbound, + PolicyRule::Accept, + "CONNTRACK"); + } + } else + { + addMgmtRule(NULL, + conntrack_dst, + conntrack_srv, + conntrack_iface, + PolicyRule::Inbound, + PolicyRule::Accept, + "CONNTRACK"); + + addMgmtRule(fw, + conntrack_dst, + conntrack_srv, + conntrack_iface, + PolicyRule::Outbound, + PolicyRule::Accept, + "CONNTRACK"); + } +} + +void AutomaticRules_ipt::addFailoverRules() +{ + Resources *os_res = Resources::os_res[fw->getStr("host_OS")]; + assert(os_res != NULL); + + string default_heartbeat_port = + os_res->getResourceStr( + "/FWBuilderResources/Target/protocols/heartbeat/default_port"); + string default_heartbeat_address = + os_res->getResourceStr( + "/FWBuilderResources/Target/protocols/heartbeat/default_address"); + string default_openais_port = + os_res->getResourceStr( + "/FWBuilderResources/Target/protocols/openais/default_port"); + string default_openais_address = + os_res->getResourceStr( + "/FWBuilderResources/Target/protocols/openais/default_address"); + + FWObjectTypedChildIterator interfaces = fw->findByType(Interface::TYPENAME); + for (; interfaces != interfaces.end(); ++interfaces) + { + Interface *iface = Interface::cast(*interfaces); + + /* + We add copies of cluster interface objects to fw objects + so each interface appears twice, the original interface + of the firewall, plus a copy of the cluster + interface. To deduplicate will use only copies of + cluster interfaces because these include VRRP interfaces. + */ + + if (iface->isFailoverInterface() && + iface->getOptionsObject()->getBool("cluster_interface")) + { + FWObject *failover_group = + iface->getFirstByType(FailoverClusterGroup::TYPENAME); + + PolicyRule *rule = NULL; + + string fw_iface_id = iface->getOptionsObject()->getStr("base_interface_id"); + Interface *fw_iface = + Interface::cast( + ruleset->getRoot()->findInIndex(FWObjectDatabase::getIntId(fw_iface_id))); + if (fw_iface == NULL) + { + throw FWException( + QString("Can not find interface of the firewall " + "for the cluster failover group %1. ") + .arg(failover_group->getName().c_str()).toStdString()); + + } + + if (failover_group->getStr("type") == "vrrp") + { + /* Add VRRP-Address to database */ + Address *vrrp_dst = Address::cast( + ruleset->getRoot()->create(IPv4::TYPENAME)); + + vrrp_dst->setName("VRRP-Address"); + vrrp_dst->setAddress(InetAddr("224.0.0.18")); + vrrp_dst->setNetmask(InetAddr(InetAddr::getAllOnes())); + vrrp_dst->setComment("VRRP Multicast Address"); + persistent_objects->add(vrrp_dst); + + bool use_ipsec_ah = false; + + FWOptions *failover_opts = + FailoverClusterGroup::cast(failover_group)->getOptionsObject(); + if (failover_opts) + { + use_ipsec_ah = failover_opts->getBool("vrrp_over_ipsec_ah"); + } + + /* Add VRRP-Service to database */ + IPService* vrrp_srv = IPService::cast( + ruleset->getRoot()->create(IPService::TYPENAME)); + vrrp_srv->setComment("VRRP service"); + vrrp_srv->setProtocolNumber(112); + persistent_objects->add(vrrp_srv); + + /* + * Add AH-Service to database. + * According to RFC 2338 section 5.3.6.3, VRRP can use + * IPsec AH. + */ + IPService* ah_srv = IPService::cast( + ruleset->getRoot()->create(IPService::TYPENAME)); + ah_srv->setComment("IPSEC-AH"); + ah_srv->setProtocolNumber(51); + persistent_objects->add(ah_srv); + + for (FWObjectTypedChildIterator it = + failover_group->findByType(FWObjectReference::TYPENAME); + it != it.end(); ++it) + { + Interface *other_iface = + Interface::cast(FWObjectReference::getObject(*it)); + assert(other_iface); + if (other_iface->getId() == fw_iface->getId()) continue; + // if interface is dynamic, we can't use it in the rule + // (because it belongs to another machine, not the fw + // we compile for so we can't use script). NULL means "any" + // in the call to addMgmtRule() + if (other_iface->isDyn()) other_iface = NULL; + + if (!use_ipsec_ah) + { + addMgmtRule(other_iface, vrrp_dst, vrrp_srv, iface, + PolicyRule::Inbound, PolicyRule::Accept, + "VRRP"); + } else + { + addMgmtRule(other_iface, vrrp_dst, ah_srv, iface, + PolicyRule::Inbound, PolicyRule::Accept, + "VRRP (with IPSEC-AH)"); + } + } + // outbound rule does not use other_interface and + // should be created outside the loop to avoid + // duplicates. Duplicates happen when cluster has 3 or + // more members. + if (!use_ipsec_ah) + { + addMgmtRule(fw, vrrp_dst, vrrp_srv, iface, + PolicyRule::Outbound, PolicyRule::Accept, + "VRRP"); + } else + { + addMgmtRule(fw, vrrp_dst, ah_srv, iface, + PolicyRule::Outbound, PolicyRule::Accept, + "VRRP (with IPSEC-AH)"); + } + } + + if (failover_group->getStr("type") == "heartbeat") + { + /* + * Note that iface is a copy of the cluster inetrface. + * Find interface of the member firewall fw that corresponds + * to the cluster interface iface + */ + + bool ucast = FailoverClusterGroup::cast(failover_group)-> + getOptionsObject()->getBool("heartbeat_unicast"); + + string addr = FailoverClusterGroup::cast(failover_group)-> + getOptionsObject()->getStr("heartbeat_address"); + if (addr.empty()) addr = default_heartbeat_address; + + string port = FailoverClusterGroup::cast(failover_group)-> + getOptionsObject()->getStr("heartbeat_port"); + if (port.empty()) port = default_heartbeat_port; + + UDPService *heartbeat_srv = UDPService::cast( + ruleset->getRoot()->create(UDPService::TYPENAME)); + + /* Add heartbeat-Address to database */ + Address *heartbeat_dst = Address::cast(ruleset->getRoot()->create( + IPv4::TYPENAME)); + heartbeat_dst->setName("HEARTBEAT-Address"); + heartbeat_dst->setAddress(InetAddr(addr)); + heartbeat_dst->setNetmask(InetAddr(InetAddr::getAllOnes())); + heartbeat_dst->setComment("HEARTBEAT Multicast Address"); + persistent_objects->add(heartbeat_dst); + + heartbeat_srv->setName("HEARTBEAT-UDP"); + heartbeat_srv->setDstRangeStart(atoi(port.c_str())); + heartbeat_srv->setDstRangeEnd(atoi(port.c_str())); + heartbeat_srv->setComment("HEARTBEAT UDP port"); + persistent_objects->add(heartbeat_srv); + + // Heartbeat can use either multicast or unicast + for (FWObjectTypedChildIterator it = + failover_group->findByType(FWObjectReference::TYPENAME); + it != it.end(); ++it) + { + Interface *other_iface = + Interface::cast(FWObjectReference::getObject(*it)); + assert(other_iface); + if (other_iface->getId() == fw_iface->getId()) continue; + // if interface is dynamic, we can't use it in the rule + // (because it belongs to another machine, not the fw + // we compile for so we can't use script). NULL means "any" + // in the call to addMgmtRule() + if (other_iface->isDyn()) other_iface = NULL; + + if (ucast) + { + addMgmtRule(other_iface, fw, heartbeat_srv, fw_iface, + PolicyRule::Inbound, PolicyRule::Accept, + "heartbeat"); + addMgmtRule(fw, other_iface, heartbeat_srv, fw_iface, + PolicyRule::Outbound, PolicyRule::Accept, + "heartbeat"); + } + else + { + addMgmtRule(other_iface, heartbeat_dst, heartbeat_srv, fw_iface, + PolicyRule::Inbound, PolicyRule::Accept, + "heartbeat"); + addMgmtRule(fw, heartbeat_dst, heartbeat_srv, fw_iface, + PolicyRule::Outbound, PolicyRule::Accept, + "heartbeat"); + } + } + } + + if (failover_group->getStr("type") == "openais") + { + string addr = FailoverClusterGroup::cast(failover_group)-> + getOptionsObject()->getStr("openais_address"); + if (addr.empty()) addr = default_openais_address; + + string port = FailoverClusterGroup::cast(failover_group)-> + getOptionsObject()->getStr("openais_port"); + if (port.empty()) port = default_openais_port; + + /* Add OPENAIS-Address to database */ + Address *openais_dst = Address::cast(ruleset->getRoot()->create( + IPv4::TYPENAME)); + openais_dst->setName("OPENAIS-Address"); + openais_dst->setAddress(InetAddr(addr)); + openais_dst->setNetmask(InetAddr(InetAddr::getAllOnes())); + openais_dst->setComment("OPENAIS Multicast Address"); + persistent_objects->add(openais_dst); + + UDPService *openais_srv = UDPService::cast( + ruleset->getRoot()->create(UDPService::TYPENAME)); + + openais_srv->setName("OPENAIS-UDP"); + openais_srv->setDstRangeStart(atoi(port.c_str())); + openais_srv->setDstRangeEnd(atoi(port.c_str())); + openais_srv->setComment("OPENAIS UDP port"); + persistent_objects->add(openais_srv); + + for (FWObjectTypedChildIterator it = + failover_group->findByType(FWObjectReference::TYPENAME); + it != it.end(); ++it) + { + Interface *other_iface = + Interface::cast(FWObjectReference::getObject(*it)); + assert(other_iface); + if (other_iface->getId() == fw_iface->getId()) continue; + // if interface is dynamic, we can't use it in the rule + // (because it belongs to another machine, not the fw + // we compile for so we can't use script). NULL means "any" + // in the call to addMgmtRule() + if (other_iface->isDyn()) other_iface = NULL; + + addMgmtRule(other_iface, openais_dst, openais_srv, iface, + PolicyRule::Inbound, PolicyRule::Accept, + "openais"); + addMgmtRule(fw, openais_dst, openais_srv, iface, + PolicyRule::Outbound, PolicyRule::Accept, + "openais"); + } + } + + if (rule) + { + FWOptions *ruleopt = rule->getOptionsObject(); + assert(ruleopt!=NULL); + ruleopt->setInt("firewall_is_part_of_any_and_networks", 1); + } + } + } +} + diff --git a/src/iptlib/AutomaticRules_ipt.h b/src/iptlib/AutomaticRules_ipt.h new file mode 100644 index 000000000..a3f186378 --- /dev/null +++ b/src/iptlib/AutomaticRules_ipt.h @@ -0,0 +1,68 @@ +/* + + Firewall Builder + + Copyright (C) 2011 NetCitadel, LLC + + Author: Vadim Kurland vadim@fwbuilder.org + + This program is free software which we release under the GNU General Public + License. You may redistribute and/or modify this program under the terms + of that 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. + + To get a copy of the GNU General Public License, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#ifndef __AUTOMATICRULES_IPT_HH__ +#define __AUTOMATICRULES_IPT_HH__ + +#include "AutomaticRules.h" + + +namespace libfwbuilder +{ + class Address; + class Firewall; + class Interface; + class Service; +}; + +namespace fwcompiler +{ + + class AutomaticRules_ipt : public AutomaticRules + { + + public: + + AutomaticRules_ipt(libfwbuilder::Firewall *fw, + libfwbuilder::Library *presistent_objects) : + AutomaticRules(fw, presistent_objects) {} + + virtual libfwbuilder::PolicyRule* addMgmtRule( + libfwbuilder::Address* src, + libfwbuilder::Address* dst, + libfwbuilder::Service* service, + libfwbuilder::Interface* iface, + const libfwbuilder::PolicyRule::Direction direction, + const libfwbuilder::PolicyRule::Action action, + const std::string &label, + bool related = false); + + void addConntrackRule(); + void addFailoverRules(); + + }; + +}; + + +#endif diff --git a/src/iptlib/CompilerDriver_ipt.cpp b/src/iptlib/CompilerDriver_ipt.cpp index e97988a1f..f58222ba1 100644 --- a/src/iptlib/CompilerDriver_ipt.cpp +++ b/src/iptlib/CompilerDriver_ipt.cpp @@ -30,13 +30,19 @@ #include "PolicyCompiler_ipt.h" #include "PolicyCompiler_secuwall.h" -#include "fwbuilder/Resources.h" -#include "fwbuilder/FWObjectDatabase.h" +#include "fwbuilder/Address.h" #include "fwbuilder/FWException.h" +#include "fwbuilder/FWObjectDatabase.h" #include "fwbuilder/Firewall.h" #include "fwbuilder/Interface.h" +#include "fwbuilder/Library.h" +#include "fwbuilder/Resources.h" #include "fwbuilder/Rule.h" #include "fwbuilder/RuleSet.h" +#include "fwbuilder/StateSyncClusterGroup.h" +#include "fwbuilder/UDPService.h" +#include "fwbuilder/FailoverClusterGroup.h" +#include "fwbuilder/IPService.h" #include #include @@ -56,6 +62,10 @@ CompilerDriver_ipt::CompilerDriver_ipt(FWObjectDatabase *db) : have_connmark_in_output = false; } +CompilerDriver_ipt::~CompilerDriver_ipt() +{ +} + // create a copy of itself, including objdb CompilerDriver* CompilerDriver_ipt::clone() { @@ -73,11 +83,10 @@ void CompilerDriver_ipt::assignRuleSetChain(RuleSet *ruleset) if (rule == NULL) continue; // skip RuleSetOptions object if (rule->isDisabled()) continue; - //rule->setStr("parent_rule_num", parentRuleNum); - if (!ruleset->isTop()) rule->setStr("ipt_chain", branch_name); - rule->setUniqueId( FWObjectDatabase::getStringId(rule->getId()) ); +// ??? +// rule->setUniqueId( FWObjectDatabase::getStringId(rule->getId()) ); } } @@ -223,4 +232,3 @@ std::auto_ptr CompilerDriver_ipt::createPolicyCompiler( return policy_compiler; } - diff --git a/src/iptlib/CompilerDriver_ipt.h b/src/iptlib/CompilerDriver_ipt.h index 52e21dd9c..5100f72ab 100644 --- a/src/iptlib/CompilerDriver_ipt.h +++ b/src/iptlib/CompilerDriver_ipt.h @@ -40,18 +40,23 @@ #include -namespace libfwbuilder { +namespace libfwbuilder +{ class FWObjectDatabase; class Cluster; class ClusterGroup; class Firewall; class RuleSet; class Interface; + class Address; + class PolicyRule; }; -namespace fwcompiler { +namespace fwcompiler +{ - class CompilerDriver_ipt : public CompilerDriver { + class CompilerDriver_ipt : public CompilerDriver + { // commands that pass control to branch chains should go into // POSTROUTING or PREROUTING chains depending on the targets used @@ -78,7 +83,8 @@ namespace fwcompiler { public: CompilerDriver_ipt(libfwbuilder::FWObjectDatabase *db); - + virtual ~CompilerDriver_ipt(); + // create a copy of itself, including objdb virtual CompilerDriver* clone(); @@ -120,7 +126,6 @@ public: int policy_af, std::map &minus_n_commands_nat); - }; }; diff --git a/src/iptlib/CompilerDriver_ipt_run.cpp b/src/iptlib/CompilerDriver_ipt_run.cpp index 6bf322e61..0a9a1e74e 100644 --- a/src/iptlib/CompilerDriver_ipt_run.cpp +++ b/src/iptlib/CompilerDriver_ipt_run.cpp @@ -47,6 +47,8 @@ #include "OSConfigurator_linux24.h" #include "OSConfigurator_secuwall.h" #include "OSConfigurator_ipcop.h" +#include "combinedAddress.h" +#include "AutomaticRules_ipt.h" #include "Configlet.h" @@ -75,6 +77,7 @@ #include #include #include +#include using namespace std; @@ -83,6 +86,14 @@ using namespace fwcompiler; extern QString user_name; +FWObject* create_combinedAddress(int id) +{ + FWObject *nobj = new combinedAddress(); + if (id > -1) nobj->setId(id); + return nobj; +} + + /* * Go through paces to compile firewall which may be a member of a * cluster. Note that both firewall and cluster are defined by their @@ -94,14 +105,17 @@ QString CompilerDriver_ipt::run(const std::string &cluster_id, const std::string &firewall_id, const std::string &single_rule_id) { - Cluster *cluster = NULL; - if (!cluster_id.empty()) - cluster = Cluster::cast( - objdb->findInIndex(objdb->getIntId(cluster_id))); - Firewall *fw = Firewall::cast( - objdb->findInIndex(objdb->getIntId(firewall_id))); - assert(fw); + FWObjectDatabase::registerObjectType(combinedAddress::TYPENAME, + &create_combinedAddress); + + // see #2212 Create temporary copy of the firewall and cluster + // objects and pass them to the compilers. + + Cluster *cluster = NULL; + Firewall *fw = NULL; + + getFirewallAndClusterObjects(cluster_id, firewall_id, &cluster, &fw); string generated_script; @@ -220,6 +234,23 @@ QString CompilerDriver_ipt::run(const std::string &cluster_id, findBranchesInMangleTable(fw, all_policies); findImportedRuleSets(fw, all_nat); + // assign unique rule ids that later will be used to generate + // chain names. This should be done after calls to + // findImportedRuleSets() + + assignUniqueRuleIds(all_policies); + assignUniqueRuleIds(all_nat); + + try + { + AutomaticRules_ipt auto_rules(fw, persistent_objects); + auto_rules.addConntrackRule(); + auto_rules.addFailoverRules(); + } catch (FWException &ex) + { + abort(ex.toString()); + } + // command line options -4 and -6 control address family for which // script will be generated. If "-4" is used, only ipv4 part will // be generated. If "-6" is used, only ipv6 part will be generated. diff --git a/src/iptlib/PolicyCompiler_ipt.cpp b/src/iptlib/PolicyCompiler_ipt.cpp index 37c95499a..51d790745 100644 --- a/src/iptlib/PolicyCompiler_ipt.cpp +++ b/src/iptlib/PolicyCompiler_ipt.cpp @@ -537,11 +537,11 @@ int PolicyCompiler_ipt::prolog() void PolicyCompiler_ipt::addPredefinedPolicyRules() { - if (getSourceRuleSet()->isTop() && !inSingleRuleCompileMode()) - { - insertConntrackRule(); - insertFailoverRule(); - } + // if (getSourceRuleSet()->isTop() && !inSingleRuleCompileMode()) + // { + // insertConntrackRule(); + // insertFailoverRule(); + // } } bool PolicyCompiler_ipt::SkipActionContinueWithNoLogging::processNext() @@ -4499,52 +4499,60 @@ string PolicyCompiler_ipt::debugPrintRule(Rule *r) ostringstream dst; string srv=" "; string time=" "; - string itf=" "; + ostringstream itf; if (srcrel->getNeg()) src << "!"; if (dstrel->getNeg()) dst << "!"; if (srvrel->getNeg()) srv = "!"; if (intrel->getNeg()) time = "!"; - if (itfrel->getNeg()) itf = "!"; + if (itfrel->getNeg()) itf << "!"; - if (i1!=srcrel->end()) { - FWObject *o=*i1; - if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer(); + if (i1!=srcrel->end()) + { + FWObject *o = FWReference::getObject(*i1); src << o->getName(); if (Group::cast(o)!=NULL) src << "[" << o->size() << "]"; } - if (i2!=dstrel->end()) { - FWObject *o=*i2; - if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer(); + if (i2!=dstrel->end()) + { + FWObject *o = FWReference::getObject(*i2); dst << o->getName(); if (Group::cast(o)!=NULL) dst << "[" << o->size() << "]"; } - if (i3!=srvrel->end()) { - FWObject *o=*i3; - if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer(); - srv+=o->getName(); + if (i3!=srvrel->end()) + { + FWObject *o = FWReference::getObject(*i3); + srv += o->getName(); } - if (i4!=intrel->end()) { - FWObject *o=*i4; - if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer(); - time+=o->getName(); + if (i4!=intrel->end()) + { + FWObject *o = FWReference::getObject(*i4); + time += o->getName(); } - if (i5!=itfrel->end()) { - FWObject *o=*i5; - if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer(); - itf+=o->getName(); + if (i5!=itfrel->end()) + { + FWObject *o = FWReference::getObject(*i5); + Interface *iface = Interface::cast(o); + itf << o->getName() << "(" << o->getId() << ")"; + if (iface) + { + if (iface->isDyn()) itf << "D"; + if (iface->isUnnumbered()) itf << "U"; + if (iface->isFailoverInterface()) itf << "F"; + } } int w=0; - if (no==0) { + if (no==0) + { str << rule->getLabel(); - w=rule->getLabel().length(); + w = rule->getLabel().length(); } str << setw(15-w) << setfill(' ') << " "; @@ -4553,7 +4561,7 @@ string PolicyCompiler_ipt::debugPrintRule(Rule *r) str << setw(18) << setfill(' ') << dst.str(); str << setw(12) << setfill(' ') << srv.c_str(); str << setw(10) << setfill(' ') << time.c_str(); - str << setw(8) << setfill(' ') << itf.c_str(); + str << setw(8) << setfill(' ') << itf.str(); if (no==0) { @@ -4574,6 +4582,8 @@ string PolicyCompiler_ipt::debugPrintRule(Rule *r) str << " pos=" << rule->getPosition(); + str << " u=" << rule->getUniqueId(); + str << " c=" << printChains(rule); str << " t=" << rule->getStr("ipt_target"); @@ -4676,430 +4686,6 @@ bool PolicyCompiler_ipt::newIptables(const string &version) XMLTools::version_compare(version, "1.2.6")>0); } -void PolicyCompiler_ipt::insertConntrackRule() -{ - FWOptions* options = fw->getOptionsObject(); - string conntrack_iface_name = options->getStr("state_sync_interface"); - if (conntrack_iface_name.empty()) - { - /* CONNTRACK not active, nothing left to do */ - return; - } - - string conntrack_group_id = options->getStr("state_sync_group_id"); - StateSyncClusterGroup *state_sync_group = - StateSyncClusterGroup::cast( - dbcopy->findInIndex( - FWObjectDatabase::getIntId(conntrack_group_id))); - - Resources *os_res = Resources::os_res[fw->getStr("host_OS")]; - assert(os_res != NULL); - - string default_address = - os_res->getResourceStr("/FWBuilderResources/Target/protocols/conntrack/default_address"); - string default_port = - os_res->getResourceStr("/FWBuilderResources/Target/protocols/conntrack/default_port"); - - bool ucast = state_sync_group->getOptionsObject()->getBool("conntrack_unicast"); - string addr = state_sync_group->getOptionsObject()->getStr("conntrack_address"); - if (addr.empty()) addr = default_address; - - try - { - InetAddr(addr); - } catch (FWException &ex) - { - try - { - InetAddr(AF_INET6, addr); - } catch (FWException &ex) - { - abort(string("Invalid IP address for conntrack: ") + addr); - } - } - - string port = state_sync_group->getOptionsObject()->getStr("conntrack_port"); - if (port.empty()) port = default_port; - - /* Add CONNTRACK-Address to database */ - Address *conntrack_dst = Address::cast(dbcopy->create(IPv4::TYPENAME)); - conntrack_dst->setName("CONNTRACK-Address"); - conntrack_dst->setAddress(InetAddr(addr)); - // Why the whole multicast adress range ? - //conntrack_dst->setNetmask(InetAddr("240.0.0.0")); - conntrack_dst->setComment("CONNTRACK Multicast Address"); - persistent_objects->add(conntrack_dst); - - UDPService *conntrack_srv = UDPService::cast(dbcopy->create(UDPService::TYPENAME)); - conntrack_srv->setName("CONNTRACK-UDP"); - conntrack_srv->setDstRangeStart(atoi(port.c_str())); - conntrack_srv->setDstRangeEnd(atoi(port.c_str())); - conntrack_srv->setComment("CONNTRACK UDP port"); - persistent_objects->add(conntrack_srv); - - /* Find conntrack interface */ - Interface* conntrack_iface = Interface::cast(fw->findObjectByName(Interface::TYPENAME, conntrack_iface_name)); - - if (conntrack_iface == NULL) - { - this->abort( - "Unable to get CONNTRACK interface ("+ conntrack_iface_name +")"); - } - - /* Add automatic rules for CONNTRACK */ - if (ucast) - { - Interface *fw_iface = NULL; - list other_interfaces; - for (FWObjectTypedChildIterator it = - state_sync_group->findByType(FWObjectReference::TYPENAME); - it != it.end(); ++it) - { - Interface *iface = - Interface::cast(FWObjectReference::getObject(*it)); - assert(iface); - if (iface->isChildOf(fw)) - { - fw_iface = iface; - } else - { - other_interfaces.push_back(iface); - } - } - foreach(Interface *other_iface, other_interfaces) - { - addMgmtRule(other_iface, - fw, - conntrack_srv, - fw_iface, - PolicyRule::Inbound, - PolicyRule::Accept, - "CONNTRACK"); - addMgmtRule(fw, - other_iface, - conntrack_srv, - fw_iface, - PolicyRule::Outbound, - PolicyRule::Accept, - "CONNTRACK"); - } - } else - { - addMgmtRule(NULL, - conntrack_dst, - conntrack_srv, - conntrack_iface, - PolicyRule::Inbound, - PolicyRule::Accept, - "CONNTRACK"); - - addMgmtRule(fw, - conntrack_dst, - conntrack_srv, - conntrack_iface, - PolicyRule::Outbound, - PolicyRule::Accept, - "CONNTRACK"); - } -} - -void PolicyCompiler_ipt::insertFailoverRule() -{ - Resources *os_res = Resources::os_res[fw->getStr("host_OS")]; - assert(os_res != NULL); - - string default_heartbeat_port = - os_res->getResourceStr( - "/FWBuilderResources/Target/protocols/heartbeat/default_port"); - string default_heartbeat_address = - os_res->getResourceStr( - "/FWBuilderResources/Target/protocols/heartbeat/default_address"); - string default_openais_port = - os_res->getResourceStr( - "/FWBuilderResources/Target/protocols/openais/default_port"); - string default_openais_address = - os_res->getResourceStr( - "/FWBuilderResources/Target/protocols/openais/default_address"); - - FWObjectTypedChildIterator interfaces = fw->findByType(Interface::TYPENAME); - for (; interfaces != interfaces.end(); ++interfaces) - { - Interface *iface = Interface::cast(*interfaces); - - /* - We add copies of cluster interface objects to fw objects - so each interface appears twice, the original interface - of the firewall, plus a copy of the cluster - interface. To deduplicate will use only copies of - cluster interfaces because these include VRRP interfaces. - */ - - if (iface->isFailoverInterface() && - iface->getOptionsObject()->getBool("cluster_interface")) - { - FWObject *failover_group = - iface->getFirstByType(FailoverClusterGroup::TYPENAME); - PolicyRule *rule = NULL; - - string fw_iface_id = iface->getOptionsObject()->getStr("base_interface_id"); - Interface *fw_iface = - Interface::cast( - dbcopy->findInIndex(FWObjectDatabase::getIntId(fw_iface_id))); - if (fw_iface == NULL) - { - warning( - QString("Can not find interface of the firewall " - "for the cluster failover group %1. " - "Falling back using cluster interface object.") - .arg(failover_group->getName().c_str()).toStdString()); - fw_iface = iface; - } - - if (failover_group->getStr("type") == "vrrp") - { - /* Add VRRP-Address to database */ - Address *vrrp_dst = Address::cast( - dbcopy->create(IPv4::TYPENAME)); - - vrrp_dst->setName("VRRP-Address"); - vrrp_dst->setAddress(InetAddr("224.0.0.18")); - vrrp_dst->setNetmask(InetAddr(InetAddr::getAllOnes())); - vrrp_dst->setComment("VRRP Multicast Address"); - persistent_objects->add(vrrp_dst); - - bool use_ipsec_ah = false; - - FWOptions *failover_opts = - FailoverClusterGroup::cast(failover_group)->getOptionsObject(); - if (failover_opts) - { - use_ipsec_ah = failover_opts->getBool("vrrp_over_ipsec_ah"); - } - - /* Add VRRP-Service to database */ - IPService* vrrp_srv = IPService::cast( - dbcopy->create(IPService::TYPENAME)); - vrrp_srv->setComment("VRRP service"); - vrrp_srv->setProtocolNumber(112); - persistent_objects->add(vrrp_srv); - - /* - * Add AH-Service to database. - * According to RFC 2338 section 5.3.6.3, VRRP can use - * IPsec AH. - */ - IPService* ah_srv = IPService::cast( - dbcopy->create(IPService::TYPENAME)); - ah_srv->setComment("IPSEC-AH"); - ah_srv->setProtocolNumber(51); - persistent_objects->add(ah_srv); - - for (FWObjectTypedChildIterator it = - failover_group->findByType(FWObjectReference::TYPENAME); - it != it.end(); ++it) - { - Interface *other_iface = - Interface::cast(FWObjectReference::getObject(*it)); - assert(other_iface); - if (other_iface->getId() == fw_iface->getId()) continue; - // if interface is dynamic, we can't use it in the rule - // (because it belongs to another machine, not the fw - // we compile for so we can't use script). NULL means "any" - // in the call to addMgmtRule() - if (other_iface->isDyn()) other_iface = NULL; - - if (!use_ipsec_ah) - { - addMgmtRule(other_iface, vrrp_dst, vrrp_srv, iface, - PolicyRule::Inbound, PolicyRule::Accept, - "VRRP"); - } else - { - addMgmtRule(other_iface, vrrp_dst, ah_srv, iface, - PolicyRule::Inbound, PolicyRule::Accept, - "VRRP (with IPSEC-AH)"); - } - } - // outbound rule does not use other_interface and - // should be created outside the loop to avoid - // duplicates. Duplicates happen when cluster has 3 or - // more members. - if (!use_ipsec_ah) - { - addMgmtRule(fw, vrrp_dst, vrrp_srv, iface, - PolicyRule::Outbound, PolicyRule::Accept, - "VRRP"); - } else - { - addMgmtRule(fw, vrrp_dst, ah_srv, iface, - PolicyRule::Outbound, PolicyRule::Accept, - "VRRP (with IPSEC-AH)"); - } - } - - if (failover_group->getStr("type") == "heartbeat") - { - /* - * Note that iface is a copy of the cluster inetrface. - * Find interface of the member firewall fw that corresponds - * to the cluster interface iface - */ - - bool ucast = FailoverClusterGroup::cast(failover_group)-> - getOptionsObject()->getBool("heartbeat_unicast"); - - string addr = FailoverClusterGroup::cast(failover_group)-> - getOptionsObject()->getStr("heartbeat_address"); - if (addr.empty()) addr = default_heartbeat_address; - - string port = FailoverClusterGroup::cast(failover_group)-> - getOptionsObject()->getStr("heartbeat_port"); - if (port.empty()) port = default_heartbeat_port; - - UDPService *heartbeat_srv = UDPService::cast( - dbcopy->create(UDPService::TYPENAME)); - - /* Add heartbeat-Address to database */ - Address *heartbeat_dst = Address::cast(dbcopy->create( - IPv4::TYPENAME)); - heartbeat_dst->setName("HEARTBEAT-Address"); - heartbeat_dst->setAddress(InetAddr(addr)); - heartbeat_dst->setNetmask(InetAddr(InetAddr::getAllOnes())); - heartbeat_dst->setComment("HEARTBEAT Multicast Address"); - persistent_objects->add(heartbeat_dst); - - heartbeat_srv->setName("HEARTBEAT-UDP"); - heartbeat_srv->setDstRangeStart(atoi(port.c_str())); - heartbeat_srv->setDstRangeEnd(atoi(port.c_str())); - heartbeat_srv->setComment("HEARTBEAT UDP port"); - persistent_objects->add(heartbeat_srv); - - // Heartbeat can use either multicast or unicast - for (FWObjectTypedChildIterator it = - failover_group->findByType(FWObjectReference::TYPENAME); - it != it.end(); ++it) - { - Interface *other_iface = - Interface::cast(FWObjectReference::getObject(*it)); - assert(other_iface); - if (other_iface->getId() == fw_iface->getId()) continue; - // if interface is dynamic, we can't use it in the rule - // (because it belongs to another machine, not the fw - // we compile for so we can't use script). NULL means "any" - // in the call to addMgmtRule() - if (other_iface->isDyn()) other_iface = NULL; - - if (ucast) - { - addMgmtRule(other_iface, fw, heartbeat_srv, fw_iface, - PolicyRule::Inbound, PolicyRule::Accept, - "heartbeat"); - addMgmtRule(fw, other_iface, heartbeat_srv, fw_iface, - PolicyRule::Outbound, PolicyRule::Accept, - "heartbeat"); - } - else - { - addMgmtRule(other_iface, heartbeat_dst, heartbeat_srv, fw_iface, - PolicyRule::Inbound, PolicyRule::Accept, - "heartbeat"); - addMgmtRule(fw, heartbeat_dst, heartbeat_srv, fw_iface, - PolicyRule::Outbound, PolicyRule::Accept, - "heartbeat"); - } - } - } - - if (failover_group->getStr("type") == "openais") - { - string addr = FailoverClusterGroup::cast(failover_group)-> - getOptionsObject()->getStr("openais_address"); - if (addr.empty()) addr = default_openais_address; - - string port = FailoverClusterGroup::cast(failover_group)-> - getOptionsObject()->getStr("openais_port"); - if (port.empty()) port = default_openais_port; - - /* Add OPENAIS-Address to database */ - Address *openais_dst = Address::cast(dbcopy->create( - IPv4::TYPENAME)); - openais_dst->setName("OPENAIS-Address"); - openais_dst->setAddress(InetAddr(addr)); - openais_dst->setNetmask(InetAddr(InetAddr::getAllOnes())); - openais_dst->setComment("OPENAIS Multicast Address"); - persistent_objects->add(openais_dst); - - UDPService *openais_srv = UDPService::cast( - dbcopy->create(UDPService::TYPENAME)); - - openais_srv->setName("OPENAIS-UDP"); - openais_srv->setDstRangeStart(atoi(port.c_str())); - openais_srv->setDstRangeEnd(atoi(port.c_str())); - openais_srv->setComment("OPENAIS UDP port"); - persistent_objects->add(openais_srv); - - for (FWObjectTypedChildIterator it = - failover_group->findByType(FWObjectReference::TYPENAME); - it != it.end(); ++it) - { - Interface *other_iface = - Interface::cast(FWObjectReference::getObject(*it)); - assert(other_iface); - if (other_iface->getId() == fw_iface->getId()) continue; - // if interface is dynamic, we can't use it in the rule - // (because it belongs to another machine, not the fw - // we compile for so we can't use script). NULL means "any" - // in the call to addMgmtRule() - if (other_iface->isDyn()) other_iface = NULL; - - addMgmtRule(other_iface, openais_dst, openais_srv, iface, - PolicyRule::Inbound, PolicyRule::Accept, - "openais"); - addMgmtRule(fw, openais_dst, openais_srv, iface, - PolicyRule::Outbound, PolicyRule::Accept, - "openais"); - } - } - - if (rule) - { - FWOptions *ruleopt = rule->getOptionsObject(); - assert(ruleopt!=NULL); - ruleopt->setInt("firewall_is_part_of_any_and_networks", 1); - } - } - } -} - - -/* TODO: Add error-handling (exceptions) */ -PolicyRule* PolicyCompiler_ipt::addMgmtRule(Address* src, - Address* dst, - Service* service, - Interface* iface, - const PolicyRule::Direction direction, - const PolicyRule::Action action, - const string label, - const bool related) -{ - PolicyRule *rule = PolicyCompiler::addMgmtRule(src, dst, service, - iface, direction, action, - label); - - FWOptions *ruleopt = rule->getOptionsObject(); assert(ruleopt!=NULL); - if (related) - { - ruleopt->setBool("stateless", false); - ruleopt->setBool("accept_established", true); - } else - { - ruleopt->setBool("stateless", true); - } - ruleopt->setBool("firewall_is_part_of_any_and_networks", true); - - return rule; -} - list PolicyCompiler_ipt::getUsedChains() { list res; diff --git a/src/iptlib/PolicyCompiler_ipt.h b/src/iptlib/PolicyCompiler_ipt.h index 5b15394da..0797eaa89 100644 --- a/src/iptlib/PolicyCompiler_ipt.h +++ b/src/iptlib/PolicyCompiler_ipt.h @@ -101,19 +101,6 @@ protected: bool isChainDescendantOfOutput(const std::string &chain_name); bool isChainDescendantOfInput(const std::string &chain_name); - void insertConntrackRule(); - void insertFailoverRule(); - - libfwbuilder::PolicyRule* addMgmtRule( - libfwbuilder::Address* src, - libfwbuilder::Address* dst, - libfwbuilder::Service* service, - libfwbuilder::Interface* iface, - const libfwbuilder::PolicyRule::Direction direction, - const libfwbuilder::PolicyRule::Action action, - const std::string label, - const bool related = false); - std::string getInterfaceVarName(libfwbuilder::FWObject *iface, bool v6=false); std::string getAddressTableVarName(libfwbuilder::FWObject *iface); diff --git a/src/iptlib/iptlib.pro b/src/iptlib/iptlib.pro index 44616cb17..36465b437 100644 --- a/src/iptlib/iptlib.pro +++ b/src/iptlib/iptlib.pro @@ -28,6 +28,7 @@ SOURCES = CompilerDriver_ipt.cpp \ RoutingCompiler_ipt.cpp \ RoutingCompiler_ipt_writers.cpp \ combinedAddress.cpp \ + AutomaticRules_ipt.cpp \ utils.cpp HEADERS = ../../config.h \ @@ -42,6 +43,7 @@ HEADERS = ../../config.h \ PolicyCompiler_secuwall.h \ RoutingCompiler_ipt.h \ combinedAddress.h \ + AutomaticRules_ipt.h \ utils.h CONFIG += staticlib diff --git a/src/libfwbuilder/src/fwbuilder/FWObject.cpp b/src/libfwbuilder/src/fwbuilder/FWObject.cpp index 7b10ea6d6..1a4755d8f 100644 --- a/src/libfwbuilder/src/fwbuilder/FWObject.cpp +++ b/src/libfwbuilder/src/fwbuilder/FWObject.cpp @@ -816,9 +816,11 @@ void FWObject::reparent(FWObject *obj, bool validate) { FWObject *old_parent = obj->getParent(); if (old_parent != NULL && old_parent != this) + { old_parent->remove(obj, false); - add(obj, validate); - obj->fixTree(); + add(obj, validate); + obj->fixTree(); + } } FWReference* FWObject::createRef() diff --git a/src/libfwbuilder/src/fwbuilder/Firewall.cpp b/src/libfwbuilder/src/fwbuilder/Firewall.cpp index d82b82212..571146ec7 100644 --- a/src/libfwbuilder/src/fwbuilder/Firewall.cpp +++ b/src/libfwbuilder/src/fwbuilder/Firewall.cpp @@ -29,29 +29,24 @@ #include -#include - #include #include #include -#include -#include #include -#include +#include #include #include - -#include +#include +#include #include - +#include #include -#include - #include - +#include #include #include +#include using namespace std; using namespace libfwbuilder; @@ -310,8 +305,6 @@ FWObject& Firewall::duplicate(const FWObject *obj, { string err="Error creating object with type: "; - map id_mapping; - checkReadOnly(); bool xro = obj->getRO(); @@ -322,29 +315,31 @@ FWObject& Firewall::duplicate(const FWObject *obj, destroyChildren(); - duplicateInterfaces(this, obj, id_mapping, preserve_id); + id_mapping_for_duplicate.clear(); + + duplicateInterfaces(this, obj, id_mapping_for_duplicate, preserve_id); for (FWObjectTypedChildIterator it = obj->findByType(Policy::TYPENAME); it != it.end(); ++it) { FWObject *new_ruleset = addCopyOf(*it, preserve_id); - id_mapping[(*it)->getId()] = new_ruleset->getId(); + id_mapping_for_duplicate[(*it)->getId()] = new_ruleset->getId(); } for (FWObjectTypedChildIterator it = obj->findByType(NAT::TYPENAME); it != it.end(); ++it) { FWObject *new_ruleset = addCopyOf(*it, preserve_id); - id_mapping[(*it)->getId()] = new_ruleset->getId(); + id_mapping_for_duplicate[(*it)->getId()] = new_ruleset->getId(); } for (FWObjectTypedChildIterator it = obj->findByType(Routing::TYPENAME); it != it.end(); ++it) { FWObject *new_ruleset = addCopyOf(*it, preserve_id); - id_mapping[(*it)->getId()] = new_ruleset->getId(); + id_mapping_for_duplicate[(*it)->getId()] = new_ruleset->getId(); } // replace references to old fw (obj) with references to this fw - id_mapping[obj->getId()] = getId(); + id_mapping_for_duplicate[obj->getId()] = getId(); FWObject *o=obj->getFirstByType( Management::TYPENAME ); addCopyOf(o,preserve_id); @@ -354,7 +349,7 @@ FWObject& Firewall::duplicate(const FWObject *obj, // replace references to old objects in rules map::iterator it; - for (it=id_mapping.begin(); it!=id_mapping.end(); ++it) + for (it=id_mapping_for_duplicate.begin(); it!=id_mapping_for_duplicate.end(); ++it) { int old_id = it->first; int new_id = it->second; @@ -459,3 +454,8 @@ list Firewall::getInterfacesByType(const string &iface_type) return res; } +void Firewall::assignUniqueRuleIds() +{ + std::for_each(begin(), end(), RuleSet::UniqueRuleIdsSetter()); +} + diff --git a/src/libfwbuilder/src/fwbuilder/Firewall.h b/src/libfwbuilder/src/fwbuilder/Firewall.h index 723a6e3a6..8133d768e 100644 --- a/src/libfwbuilder/src/fwbuilder/Firewall.h +++ b/src/libfwbuilder/src/fwbuilder/Firewall.h @@ -31,6 +31,8 @@ #include // for time_t #include +#include + namespace libfwbuilder { @@ -42,7 +44,8 @@ namespace libfwbuilder class Firewall : public Host { - + std::map id_mapping_for_duplicate; + void duplicateInterfaces(FWObject *target, const FWObject *source, std::map &id_mapping, @@ -70,7 +73,7 @@ public: /** * verify whether given object type is approppriate as a child */ - virtual bool validateChild(FWObject *o); + virtual bool validateChild(FWObject *o); virtual FWOptions* getOptionsObject(); @@ -91,10 +94,27 @@ public: */ virtual FWObject& duplicateForUndo(const FWObject *obj) throw(FWException); + /* + * Return id mapping table created during latest run of duplicate() + */ + const std::map& getIDMappingTable() + { + return id_mapping_for_duplicate; + } + Policy *getPolicy(); NAT *getNAT(); Routing *getRouting(); + /** + * scan all rules of all rule sets and call setUniqueId() to set + * unique string id for each rule. These IDs will be carried + * through calls to duplicate() when firewall object and its rule + * sets are cloned. These IDs are used by compilers to generate + * stable labels for chains and such. + */ + void assignUniqueRuleIds(); + /** * Return list of interfaces of given type. This walks all interfaces recursively, * including subinterfaces. diff --git a/src/libfwbuilder/src/fwbuilder/Rule.cpp b/src/libfwbuilder/src/fwbuilder/Rule.cpp index 57ea3374f..c9b0bf396 100644 --- a/src/libfwbuilder/src/fwbuilder/Rule.cpp +++ b/src/libfwbuilder/src/fwbuilder/Rule.cpp @@ -90,7 +90,6 @@ FWObject& Rule::shallowDuplicate(const FWObject *x, unique_id = rx->unique_id; abs_rule_number = rx->abs_rule_number; compiler_message = rx->compiler_message; - return FWObject::shallowDuplicate(x,preserve_id); } diff --git a/src/libfwbuilder/src/fwbuilder/RuleSet.cpp b/src/libfwbuilder/src/fwbuilder/RuleSet.cpp index 3bda36b6d..9eff35757 100644 --- a/src/libfwbuilder/src/fwbuilder/RuleSet.cpp +++ b/src/libfwbuilder/src/fwbuilder/RuleSet.cpp @@ -370,4 +370,15 @@ int RuleSet::getRuleSetSize() return getChildrenCount() - 1; } +void RuleSet::assignUniqueRuleIds() +{ + for (FWObject::iterator it=begin(); it!=end(); ++it) + { + Rule *r = Rule::cast(*it); + if (r != NULL) + r->setUniqueId(FWObjectDatabase::getStringId((*it)->getId()) ); + + } +} + diff --git a/src/libfwbuilder/src/fwbuilder/RuleSet.h b/src/libfwbuilder/src/fwbuilder/RuleSet.h index 33eac4e55..b55a5a79a 100644 --- a/src/libfwbuilder/src/fwbuilder/RuleSet.h +++ b/src/libfwbuilder/src/fwbuilder/RuleSet.h @@ -114,12 +114,31 @@ class RuleSet : public FWObject int getRuleSetSize(); - virtual Rule* createRule() =0; + virtual Rule* createRule() = 0; virtual bool isPrimaryObject() const { return false; } void renumberRules(); + /** + * scan all rules of all rule sets and call setUniqueId() to set + * unique string id for each rule. These IDs will be carried + * through calls to duplicate() when firewall object and its rule + * sets are cloned. These IDs are used by compilers to generate + * stable labels for chains and such. + */ + void assignUniqueRuleIds(); + + struct UniqueRuleIdsSetter + { + void operator()(FWObject *o) + { + RuleSet *rs = RuleSet::cast(o); + if (rs != NULL) rs->assignUniqueRuleIds(); + } + }; + + }; //__RULESET_HH_FLAG__ } diff --git a/src/libfwbuilder/src/fwcompiler/Compiler.cpp b/src/libfwbuilder/src/fwcompiler/Compiler.cpp index bff1cf44d..0c08bc6cf 100644 --- a/src/libfwbuilder/src/fwcompiler/Compiler.cpp +++ b/src/libfwbuilder/src/fwcompiler/Compiler.cpp @@ -159,12 +159,17 @@ void Compiler::_init(FWObjectDatabase *_db, Firewall *_fw) { assert(_fw->getRoot() == _db); - string fw_str_id = FWObjectDatabase::getStringId(_fw->getId()); - dbcopy = new FWObjectDatabase(*_db); // copies entire tree - fw = Firewall::cast( - dbcopy->findInIndex(FWObjectDatabase::getIntId(fw_str_id))); + dbcopy = _db; + fw = _fw; fwopt = fw->getOptionsObject(); fw_id = fw->getId(); + + // string fw_str_id = FWObjectDatabase::getStringId(_fw->getId()); + // dbcopy = new FWObjectDatabase(*_db); // copies entire tree + // fw = Firewall::cast( + // dbcopy->findInIndex(FWObjectDatabase::getIntId(fw_str_id))); + // fwopt = fw->getOptionsObject(); + // fw_id = fw->getId(); } } @@ -213,6 +218,7 @@ Compiler::Compiler(FWObjectDatabase*, bool ipv6_policy) Compiler::~Compiler() { +#ifdef DBCOPY_IS_TRUE_COPY if (dbcopy) { if (dbcopy->verifyTree()) @@ -227,6 +233,8 @@ Compiler::~Compiler() delete dbcopy; } +#endif + dbcopy = NULL; } diff --git a/src/libfwbuilder/src/fwcompiler/NATCompiler.cpp b/src/libfwbuilder/src/fwcompiler/NATCompiler.cpp index 23c892b17..6dbbb0c61 100644 --- a/src/libfwbuilder/src/fwcompiler/NATCompiler.cpp +++ b/src/libfwbuilder/src/fwcompiler/NATCompiler.cpp @@ -88,10 +88,10 @@ int NATCompiler::prolog() //if (r->isDisabled()) continue; //r->setInterfaceId(-1); + if (r->getLabel().empty()) + r->setLabel( createRuleLabel(label_prefix, "NAT", r->getPosition()) ); - r->setLabel( createRuleLabel(label_prefix, "NAT", r->getPosition()) ); r->setAbsRuleNumber(global_num); global_num++; - r->setUniqueId( FWObjectDatabase::getStringId(r->getId()) ); rule_counter++; } diff --git a/src/libfwbuilder/src/fwcompiler/PolicyCompiler.cpp b/src/libfwbuilder/src/fwcompiler/PolicyCompiler.cpp index e7c18b6d6..7018c8a08 100644 --- a/src/libfwbuilder/src/fwcompiler/PolicyCompiler.cpp +++ b/src/libfwbuilder/src/fwcompiler/PolicyCompiler.cpp @@ -101,27 +101,31 @@ int PolicyCompiler::prolog() */ //if (r->isDisabled()) continue; - RuleElementItf *itfre = r->getItf(); - assert(itfre); + if (r->getLabel().empty()) + { + RuleElementItf *itfre = r->getItf(); + assert(itfre); - if (itfre->isAny()) - { - r->setLabel( createRuleLabel(label_prefix, - "global", r->getPosition()) ); - } else - { - string interfaces = ""; - for (FWObject::iterator i=itfre->begin(); i!=itfre->end(); ++i) + if (itfre->isAny()) { - FWObject *o = FWReference::getObject(*i); - if (interfaces!="") interfaces += ","; - interfaces += o->getName(); + r->setLabel( createRuleLabel(label_prefix, + "global", r->getPosition()) ); + } else + { + string interfaces = ""; + for (FWObject::iterator i=itfre->begin(); i!=itfre->end(); ++i) + { + FWObject *o = FWReference::getObject(*i); + if (interfaces!="") interfaces += ","; + interfaces += o->getName(); + } + r->setLabel( createRuleLabel(label_prefix, + interfaces, r->getPosition()) ); } - r->setLabel( createRuleLabel(label_prefix, - interfaces, r->getPosition()) ); } - r->setAbsRuleNumber(global_num); global_num++; - r->setUniqueId( FWObjectDatabase::getStringId(r->getId()) ); + + r->setAbsRuleNumber(global_num); + global_num++; rule_counter++; } @@ -1131,16 +1135,19 @@ string PolicyCompiler::debugPrintRule(Rule *r) srv_id = o->getId(); } - if (i4!=itfrel->end()) { - FWObject *o=*i4; - if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer(); - itf+=o->getName(); + if (i4!=itfrel->end()) + { + ostringstream str; + FWObject *o = FWReference::getObject(*i4); + str << o->getName() << "(" << o->getId() << ")"; + itf += str.str(); } - int w=0; - if (no==0) { + int w = 0; + if (no==0) + { str << rule->getLabel(); - w=rule->getLabel().length(); + w = rule->getLabel().length(); } str << setw(10-w) << setfill(' ') << " "; diff --git a/src/libfwbuilder/src/fwcompiler/RoutingCompiler.cpp b/src/libfwbuilder/src/fwcompiler/RoutingCompiler.cpp index 2825b3e45..519dc5f9c 100644 --- a/src/libfwbuilder/src/fwcompiler/RoutingCompiler.cpp +++ b/src/libfwbuilder/src/fwcompiler/RoutingCompiler.cpp @@ -86,7 +86,10 @@ int RoutingCompiler::prolog() { Rule *r = Rule::cast(*i); if (r == NULL) continue; // skip RuleSetOptions object - r->setLabel( createRuleLabel("", "main", r->getPosition()) ); + + if (r->getLabel().empty()) + r->setLabel( createRuleLabel("", "main", r->getPosition()) ); + rule_counter++; } diff --git a/src/pf/pf.cpp b/src/pf/pf.cpp index 5a5924dad..d0d409bd0 100644 --- a/src/pf/pf.cpp +++ b/src/pf/pf.cpp @@ -147,15 +147,19 @@ int main(int argc, char **argv) FWObject *slib = objdb->getById(FWObjectDatabase::STANDARD_LIB_ID); if (slib && slib->isReadOnly()) slib->setReadOnly(false); - CompilerDriver_pf driver(objdb); - if (!driver.prepare(args)) + CompilerDriver_pf *driver = new CompilerDriver_pf(objdb); + if (!driver->prepare(args)) { usage(argv[0]); exit(1); } - driver.compile(); + driver->compile(); + int ret = (driver->getStatus() == BaseCompiler::FWCOMPILER_SUCCESS) ? 0 : 1; + + delete driver; delete objdb; - return (driver.getStatus() == BaseCompiler::FWCOMPILER_SUCCESS) ? 0 : 1; + + return ret; } catch(const FWException &ex) { diff --git a/src/pflib/CompilerDriver_ipf_run.cpp b/src/pflib/CompilerDriver_ipf_run.cpp index 5beecfdbf..34a6eb9ed 100644 --- a/src/pflib/CompilerDriver_ipf_run.cpp +++ b/src/pflib/CompilerDriver_ipf_run.cpp @@ -159,13 +159,9 @@ QString CompilerDriver_ipf::run(const std::string &cluster_id, const std::string &single_rule_id) { Cluster *cluster = NULL; - if (!cluster_id.empty()) - cluster = Cluster::cast( - objdb->findInIndex(objdb->getIntId(cluster_id))); + Firewall *fw = NULL; - Firewall *fw = Firewall::cast( - objdb->findInIndex(objdb->getIntId(firewall_id))); - assert(fw); + getFirewallAndClusterObjects(cluster_id, firewall_id, &cluster, &fw); try { diff --git a/src/pflib/CompilerDriver_ipfw_run.cpp b/src/pflib/CompilerDriver_ipfw_run.cpp index 6a17c594d..9dd5ec090 100644 --- a/src/pflib/CompilerDriver_ipfw_run.cpp +++ b/src/pflib/CompilerDriver_ipfw_run.cpp @@ -109,13 +109,9 @@ QString CompilerDriver_ipfw::run(const std::string &cluster_id, const std::string &single_rule_id) { Cluster *cluster = NULL; - if (!cluster_id.empty()) - cluster = Cluster::cast( - objdb->findInIndex(objdb->getIntId(cluster_id))); + Firewall *fw = NULL; - Firewall *fw = Firewall::cast( - objdb->findInIndex(objdb->getIntId(firewall_id))); - assert(fw); + getFirewallAndClusterObjects(cluster_id, firewall_id, &cluster, &fw); try { @@ -169,6 +165,13 @@ QString CompilerDriver_ipfw::run(const std::string &cluster_id, findImportedRuleSets(fw, all_policies); + // assign unique rule ids that later will be used to generate + // chain names. This should be done after calls to + // findImportedRuleSets() + // NB: these ids are not used by this compiler + + assignUniqueRuleIds(all_policies); + // command line options -4 and -6 control address family for which // script will be generated. If "-4" is used, only ipv4 part will // be generated. If "-6" is used, only ipv6 part will be generated. diff --git a/src/pflib/CompilerDriver_pf_run.cpp b/src/pflib/CompilerDriver_pf_run.cpp index de9f88a1b..3d5f7c7db 100644 --- a/src/pflib/CompilerDriver_pf_run.cpp +++ b/src/pflib/CompilerDriver_pf_run.cpp @@ -206,13 +206,9 @@ QString CompilerDriver_pf::run(const std::string &cluster_id, const std::string &single_rule_id) { Cluster *cluster = NULL; - if (!cluster_id.empty()) - cluster = Cluster::cast( - objdb->findInIndex(objdb->getIntId(cluster_id))); + Firewall *fw = NULL; - Firewall *fw = Firewall::cast( - objdb->findInIndex(objdb->getIntId(firewall_id))); - assert(fw); + getFirewallAndClusterObjects(cluster_id, firewall_id, &cluster, &fw); try { @@ -282,6 +278,14 @@ QString CompilerDriver_pf::run(const std::string &cluster_id, findImportedRuleSets(fw, all_policies); findImportedRuleSets(fw, all_nat); + // assign unique rule ids that later will be used to generate + // chain names. This should be done after calls to + // findImportedRuleSets() + // NB: these ids are not really used by compiler for PF + + assignUniqueRuleIds(all_policies); + assignUniqueRuleIds(all_nat); + list all_rulesets; all_rulesets.insert( all_rulesets.begin(), all_policies.begin(), all_policies.end()); diff --git a/src/pix/pix.cpp b/src/pix/pix.cpp index d2978e250..e94dd9769 100644 --- a/src/pix/pix.cpp +++ b/src/pix/pix.cpp @@ -162,21 +162,23 @@ int main(int argc, char **argv) FWObject *slib = objdb->getById(FWObjectDatabase::STANDARD_LIB_ID); if (slib && slib->isReadOnly()) slib->setReadOnly(false); - CompilerDriver_pix driver(objdb); - if (!driver.prepare(args)) + CompilerDriver_pix *driver = new CompilerDriver_pix(objdb); + if (!driver->prepare(args)) { usage(argv[0]); exit(1); } if (only_print_inspection_code) { - cout << driver.protocolInspectorCommands(); + cout << driver->protocolInspectorCommands(); } else - driver.compile(); + driver->compile(); + int ret = (driver->getStatus() == BaseCompiler::FWCOMPILER_SUCCESS) ? 0 : 1; + delete driver; delete objdb; - return (driver.getStatus() == BaseCompiler::FWCOMPILER_SUCCESS) ? 0 : 1; + return ret; } catch(libfwbuilder::FWException &ex) { diff --git a/src/procurve_acl/procurve_acl.cpp b/src/procurve_acl/procurve_acl.cpp index e8315e3f3..3a84435d5 100644 --- a/src/procurve_acl/procurve_acl.cpp +++ b/src/procurve_acl/procurve_acl.cpp @@ -153,17 +153,20 @@ int main(int argc, char **argv) FWObject *slib = objdb->getById(FWObjectDatabase::STANDARD_LIB_ID); if (slib && slib->isReadOnly()) slib->setReadOnly(false); - CompilerDriver_procurve_acl driver(objdb); - if (!driver.prepare(args)) + CompilerDriver_procurve_acl *driver = new CompilerDriver_procurve_acl(objdb); + if (!driver->prepare(args)) { usage(argv[0]); exit(1); } - driver.compile(); + driver->compile(); + int ret = (driver->getStatus() == BaseCompiler::FWCOMPILER_SUCCESS) ? 0 : 1; + + delete driver; delete objdb; - return (driver.getStatus() == BaseCompiler::FWCOMPILER_SUCCESS) ? 0 : 1; + return ret; } catch(libfwbuilder::FWException &ex) {