QString CompilerDriver_pix::run(const std::string &cluster_id, const std::string &firewall_id, const std::string &single_rule_id) { Cluster *cluster = NULL; Firewall *fw = NULL; getFirewallAndClusterObjects(cluster_id, firewall_id, &cluster, &fw); // Copy rules from the cluster object populateClusterElements(cluster, fw); if (cluster) { // PIX failover is dfferent from VRRP and other failover protocols // in that it does not create new virtual address. Instead, each // unit is configured with two ip addresses, one for the active // unit and another for standby one. When active unit fails, the // other one assumes its address. // // This matters because when we use cluster object or one of its // interfaces in rules, compiler should expand it to the set of // addresses that includes addresses of the corresponding // interface of both member firewalls. Method // CompilerDriver::copyFailoverInterface adds a copy of firewall // interface to the cluster object. This works for all firewalls, // but for PIX we need to add copies of interfaces from both // members. // FWObjectTypedChildIterator cl_iface = cluster->findByType(Interface::TYPENAME); for (; cl_iface != cl_iface.end(); ++cl_iface) { FailoverClusterGroup *failover_group = FailoverClusterGroup::cast( (*cl_iface)->getFirstByType(FailoverClusterGroup::TYPENAME)); if (failover_group) { //FWObject *this_member_interface = NULL; //UNUSED list<FWObject*> other_member_interfaces; for (FWObjectTypedChildIterator it = failover_group->findByType(FWObjectReference::TYPENAME); it != it.end(); ++it) { FWObject *intf = FWObjectReference::getObject(*it); assert(intf); //if (intf->isChildOf(fw)) this_member_interface = intf; //UNUSED //else other_member_interfaces.push_back(intf); if (!intf->isChildOf(fw)) other_member_interfaces.push_back(intf); } if (!other_member_interfaces.empty()) { for (list<FWObject*>::iterator it=other_member_interfaces.begin(); it!=other_member_interfaces.end(); ++it) { cluster->addCopyOf(*it, true); } } } } } #if 0 FWObjectTypedChildIterator iface = fw->findByType(Interface::TYPENAME); for (; iface != iface.end(); ++iface) { (*iface)->dump(true, true); } #endif determineOutputFileNames(cluster, fw, !cluster_id.empty(), QStringList(""), QStringList("fw"), QStringList("")); FWOptions* options = fw->getOptionsObject(); QString script_buffer; std::auto_ptr<NATCompiler_pix> n; std::auto_ptr<PolicyCompiler_pix> c; std::auto_ptr<RoutingCompiler_pix> r; try { clearReadOnly(fw); commonChecks2(cluster, fw); pixClusterConfigurationChecks(cluster, fw); // Note that fwobjectname may be different from the name of the // firewall fw This happens when we compile a member of a cluster current_firewall_name = fw->getName().c_str(); bool pix_acl_basic = options->getBool("pix_acl_basic"); bool pix_acl_no_clear = options->getBool("pix_acl_no_clear"); bool pix_acl_substitution = options->getBool("pix_acl_substitution"); bool pix_add_clear_statements = options->getBool("pix_add_clear_statements"); if (!pix_acl_basic && !pix_acl_no_clear && !pix_acl_substitution) { if ( pix_add_clear_statements ) options->setBool("pix_acl_basic",true); else options->setBool("pix_acl_no_clear",true); } list<FWObject*> all_interfaces = fw->getByTypeDeep(Interface::TYPENAME); pixSecurityLevelChecks(fw, all_interfaces); pixNetworkZoneChecks(fw, all_interfaces); /* Now that all checks are done, we can drop copies of cluster * interfaces that were added to the firewall by * CompilerDriver::populateClusterElements() */ list<FWObject*> copies_of_cluster_interfaces; for (std::list<FWObject*>::iterator i=all_interfaces.begin(); i!=all_interfaces.end(); ++i) { Interface *iface = Interface::cast(*i); assert(iface); if (iface->getOptionsObject()->getBool("cluster_interface")) copies_of_cluster_interfaces.push_back(iface); } while (copies_of_cluster_interfaces.size()) { fw->remove(copies_of_cluster_interfaces.front()); copies_of_cluster_interfaces.pop_front(); } NamedObjectsManagerPIX named_objects_manager(persistent_objects, fw); all_interfaces = fw->getByTypeDeep(Interface::TYPENAME); for (std::list<FWObject*>::iterator i=all_interfaces.begin(); i!=all_interfaces.end(); ++i) { Interface *iface = Interface::cast(*i); assert(iface); /* * missing labels on interfaces * */ if (iface->getLabel()=="") { string lbl; if (iface->isDedicatedFailover()) { // dedicated failover interface misses label. This // interface can be used in failover cluster group // or state sync group. Assign label depending on // the function. FWObjectTypedChildIterator it = cluster->findByType(StateSyncClusterGroup::TYPENAME); StateSyncClusterGroup *state_sync_group = StateSyncClusterGroup::cast(*it); if (state_sync_group && state_sync_group->hasMember(iface)) lbl = "state"; if (!iface->getOptionsObject()->getStr("failover_group_id").empty()) lbl = "failover"; } if (lbl.empty()) { if (iface->getSecurityLevel()==0) lbl="outside"; else { if (iface->getSecurityLevel()==100) lbl="inside"; else { QString l("dmz%1"); lbl = l.arg(iface->getSecurityLevel()).toStdString(); } } } iface->setLabel(lbl); } } /* * now sort interfaces by their network zone "width" (that * is, more narrow network zone should go first, interface * with network zone "any" should be the last) * std::sort(fw->begin(), fw->end(), sort_by_net_zone() ); */ try { AutomaticRules_cisco auto_rules(fw, persistent_objects); auto_rules.addSshAccessRule(); } catch (FWException &ex) { abort(ex.toString()); } std::auto_ptr<Preprocessor> prep( new Preprocessor(objdb , fw, false)); if (inTestMode()) prep->setTestMode(); if (inEmbeddedMode()) prep->setEmbeddedMode(); prep->compile(); std::auto_ptr<OSConfigurator> oscnf( new OSConfigurator_pix_os(objdb , fw, false)); if (inTestMode()) oscnf->setTestMode(); if (inEmbeddedMode()) oscnf->setEmbeddedMode(); oscnf->prolog(); oscnf->processFirewallOptions(); bool have_named_objects = false; bool have_object_groups = false; /* create compilers and run the whole thing */ string version = fw->getStr("version"); if (XMLTools::version_compare(version, "8.3")>=0) n = std::auto_ptr<NATCompiler_pix>( new NATCompiler_asa8(objdb, fw, false, oscnf.get())); else n = std::auto_ptr<NATCompiler_pix>( new NATCompiler_pix(objdb, fw, false, oscnf.get())); RuleSet *nat = RuleSet::cast(fw->getFirstByType(NAT::TYPENAME)); if (nat) { nat->assignUniqueRuleIds(); n->setNamedObjectsManager(&named_objects_manager); n->setSourceRuleSet(nat); n->setRuleSetName(nat->getName()); n->setPersistentObjects(persistent_objects); if (inTestMode()) n->setTestMode(); if (inEmbeddedMode()) n->setEmbeddedMode(); n->setSingleRuleCompileMode(single_rule_id); n->setDebugLevel( dl ); if (rule_debug_on) n->setDebugRule( drn ); n->setVerbose( verbose ); if ( n->prolog() > 0 ) { n->compile(); n->epilog(); preamble_commands += n->printPreambleCommands(); clear_commands += n->printClearCommands(); have_named_objects = (have_named_objects || named_objects_manager.haveNamedObjects()); have_object_groups = (have_object_groups || named_objects_manager.haveObjectGroups()); //named_objects_manager.saveObjectGroups(); } else info(" Nothing to compile in NAT"); } c = std::auto_ptr<PolicyCompiler_pix>( new PolicyCompiler_pix(objdb, fw, false, oscnf.get() , n.get())); RuleSet *policy = RuleSet::cast(fw->getFirstByType(Policy::TYPENAME)); if (policy) { policy->assignUniqueRuleIds(); c->setNamedObjectsManager(&named_objects_manager); c->setSourceRuleSet(policy); c->setRuleSetName(policy->getName()); c->setPersistentObjects(persistent_objects); if (inTestMode()) c->setTestMode(); if (inEmbeddedMode()) c->setEmbeddedMode(); c->setSingleRuleCompileMode(single_rule_id); c->setDebugLevel( dl ); if (rule_debug_on) c->setDebugRule( drp ); c->setVerbose( verbose ); if ( c->prolog() > 0 ) { c->compile(); c->epilog(); preamble_commands += c->printPreambleCommands(); clear_commands += c->printClearCommands(); have_named_objects = (have_named_objects || named_objects_manager.haveNamedObjects()); have_object_groups = (have_object_groups || named_objects_manager.haveObjectGroups()); //named_objects_manager.saveObjectGroups(); } else info(" Nothing to compile in Policy"); } r = std::auto_ptr<RoutingCompiler_pix>( new RoutingCompiler_pix(objdb, fw, false, oscnf.get())); RuleSet *routing = RuleSet::cast(fw->getFirstByType(Routing::TYPENAME)); if (routing) { routing->assignUniqueRuleIds(); r->setNamedObjectsManager(&named_objects_manager); r->setSourceRuleSet(routing); r->setRuleSetName(routing->getName()); r->setPersistentObjects(persistent_objects); if (inTestMode()) r->setTestMode(); if (inEmbeddedMode()) r->setEmbeddedMode(); r->setSingleRuleCompileMode(single_rule_id); r->setDebugLevel( dl ); if (rule_debug_on) r->setDebugRule( drp ); r->setVerbose( verbose ); if ( r->prolog() > 0 ) { r->compile(); r->epilog(); } else info(" Nothing to compile in Routing"); } /* * compilers detach persistent objects when they finish, this * means at this point library persistent_objects is not part * of any object tree. */ objdb->reparent(persistent_objects); if (haveErrorsAndWarnings()) { all_errors.push_front(getErrors("").c_str()); } policy_script = c->getCompiledScript(); nat_script = n->getCompiledScript(); routing_script = r->getCompiledScript(); named_objects_and_groups = named_objects_manager.getNamedObjectsDefinitions(); if (c->haveErrorsAndWarnings()) all_errors.push_back(c->getErrors("C ").c_str()); if (n->haveErrorsAndWarnings()) all_errors.push_back(n->getErrors("N ").c_str()); if (r->haveErrorsAndWarnings()) all_errors.push_back(r->getErrors("R ").c_str()); if (single_rule_compile_on) { return formSingleRuleCompileOutput( QString::fromUtf8( (named_objects_and_groups + policy_script + nat_script + routing_script).c_str())); } system_configuration_script = oscnf->getCompiledScript(); system_configuration_script += "\n"; clear_commands += named_objects_manager.getClearCommands() + "\n"; // system_configuration_script += preamble_commands; // system_configuration_script += clear_commands; script_buffer = assembleFwScript( cluster, fw, !cluster_id.empty(), oscnf.get()); QString ofname = getAbsOutputFileName(file_names[FW_FILE]); info("Output file name: " + ofname.toStdString()); QFile fw_file(ofname); if (fw_file.open(QIODevice::WriteOnly)) { QTextStream fw_str(&fw_file); fw_str << script_buffer; fw_file.close(); fw_file.setPermissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ReadGroup | QFile::ReadOther | QFile::ExeOwner | QFile::ExeGroup | QFile::ExeOther ); info(" Compiled successfully"); } else { QString err(" Failed to open file %1 for writing: %2; Current dir: %3"); abort(err.arg(fw_file.fileName()) .arg(fw_file.error()).arg(QDir::current().path()).toStdString()); } if (!all_errors.isEmpty()) status = BaseCompiler::FWCOMPILER_WARNING; } catch (FWException &ex) { status = BaseCompiler::FWCOMPILER_ERROR; return QString::fromUtf8(ex.toString().c_str()); } return ""; }