diff --git a/doc/ChangeLog b/doc/ChangeLog index 81a9b14ef..cc799b23e 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,14 @@ +2011-03-16 vadim + + * Importer.cpp (prepareForDeduplication): fixed #1548 "Object + de-duplication during import process". Also SourceForge bug + 2980566 "Import from hostsfile may cause duplicate Objects" and + 3030072 "remove duplicates during any import". Now the program can + optionally re-use existing objects from both Standard Objects and + user-defined libraries when it imports existing firewall + configuration. This works for any firewall platform for which we + support policy import. + 2011-03-14 vadim * pix.g (named_object_network): see #2223 Implemented import of diff --git a/src/import/Importer.cpp b/src/import/Importer.cpp index 9816b3fba..93338bfd2 100644 --- a/src/import/Importer.cpp +++ b/src/import/Importer.cpp @@ -135,6 +135,12 @@ Importer::Importer(FWObject *_lib, service_maker = new ServiceObjectMaker(Library::cast(library)); } +void Importer::prepareForDeduplication() +{ + address_maker->prepareForDeduplication(library->getRoot()); + service_maker->prepareForDeduplication(library->getRoot()); +} + void Importer::run() { // create and run parsers in derived classes diff --git a/src/import/Importer.h b/src/import/Importer.h index 6f8e6c95d..7d6139e54 100644 --- a/src/import/Importer.h +++ b/src/import/Importer.h @@ -263,7 +263,8 @@ public: void setFileName(const std::string &fn) { input_file_name = fn; } void setPlatform(const std::string &pl) { platform = pl; } - + void prepareForDeduplication(); + // add standard line to rule comment, this adds something like // "created during import from , line " void addStandardImportComment(libfwbuilder::FWObject *obj, diff --git a/src/import/objectMaker.cpp b/src/import/objectMaker.cpp index 53b2b1159..ee85436f1 100644 --- a/src/import/objectMaker.cpp +++ b/src/import/objectMaker.cpp @@ -30,6 +30,7 @@ #include "fwbuilder/FWObject.h" #include "fwbuilder/FWObjectDatabase.h" #include "fwbuilder/ICMPService.h" +#include "fwbuilder/ICMP6Service.h" #include "fwbuilder/IPService.h" #include "fwbuilder/IPv4.h" #include "fwbuilder/IPv6.h" @@ -40,6 +41,13 @@ #include "fwbuilder/TCPService.h" #include "fwbuilder/TagService.h" #include "fwbuilder/UDPService.h" +#include "fwbuilder/physAddress.h" + +#include "fwbuilder/Rule.h" +#include "fwbuilder/RuleSet.h" +#include "fwbuilder/FWReference.h" +#include "fwbuilder/Host.h" +#include "fwbuilder/FWOptions.h" #include "QStringListOperators.h" @@ -48,6 +56,9 @@ #include +#include + + extern int fwbdebug; using namespace libfwbuilder; @@ -76,7 +87,7 @@ QString ObjectSignature::toString() const if (type_name == CustomService::TYPENAME) sig << platform << code << protocol_name; - if (type_name == ICMPService::TYPENAME) + if (type_name == ICMPService::TYPENAME || type_name == ICMP6Service::TYPENAME) sig << icmp_type << icmp_code; if (type_name == IPService::TYPENAME) @@ -98,6 +109,150 @@ QString ObjectSignature::toString() const return sig.join("|-|"); } +void* ObjectSignature::dispatch(Network *obj, void*) +{ + type_name = obj->getTypeName().c_str(); + address = obj->getAddressPtr()->toString().c_str(); + netmask = obj->getNetmaskPtr()->toString().c_str(); + return this; +} + +void* ObjectSignature::dispatch(NetworkIPv6 *obj, void*) +{ + type_name = obj->getTypeName().c_str(); + address = obj->getAddressPtr()->toString().c_str(); + netmask = obj->getNetmaskPtr()->toString().c_str(); + return this; +} + +void* ObjectSignature::dispatch(IPv4 *obj, void*) +{ + type_name = obj->getTypeName().c_str(); + address = obj->getAddressPtr()->toString().c_str(); + netmask = InetAddr::getAllOnes().toString().c_str(); + return this; +} + +void* ObjectSignature::dispatch(IPv6 *obj, void*) +{ + type_name = obj->getTypeName().c_str(); + address = obj->getAddressPtr()->toString().c_str(); + netmask = InetAddr::getAllOnes(AF_INET6).toString().c_str(); + return this; +} + +void* ObjectSignature::dispatch(AddressRange *obj, void*) +{ + type_name = obj->getTypeName().c_str(); + address_range_start = obj->getRangeStart().toString().c_str(); + address_range_end = obj->getRangeEnd().toString().c_str(); + return this; +} + +/* + * Note that we do not track "compile time" / "run time" attribute of + * the object because on import, only "run time" make sense + */ +void* ObjectSignature::dispatch(AddressTable *obj, void*) +{ + type_name = obj->getTypeName().c_str(); + address_table_name = obj->getSourceName().c_str(); + return this; +} + +void* ObjectSignature::dispatch(physAddress *obj, void*) +{ + type_name = obj->getTypeName().c_str(); + address = obj->getPhysAddress().c_str(); + return this; +} + +void* ObjectSignature::dispatch(IPService *obj, void*) +{ + type_name = obj->getTypeName().c_str(); + protocol = obj->getProtocolNumber(); + fragments = obj->getBool("fragm") || obj->getBool("short_fragm"); + return this; +} + +void* ObjectSignature::dispatch(ICMPService *obj, void*) +{ + type_name = obj->getTypeName().c_str(); + icmp_type = obj->getInt("type"); + icmp_code = obj->getInt("code"); + return this; +} + +void* ObjectSignature::dispatch(ICMP6Service *obj, void*) +{ + type_name = obj->getTypeName().c_str(); + icmp_type = obj->getInt("type"); + icmp_code = obj->getInt("code"); + return this; +} + +void* ObjectSignature::dispatch(TCPService *obj, void*) +{ + type_name = obj->getTypeName().c_str(); + src_port_range_start = obj->getSrcRangeStart(); + src_port_range_end = obj->getSrcRangeEnd(); + dst_port_range_start = obj->getDstRangeStart(); + dst_port_range_end = obj->getDstRangeEnd(); + established = obj->getEstablished(); + + set flags = obj->getAllTCPFlags(); + set::iterator it; + for (it=flags.begin(); it!=flags.end(); ++it) flags_comp << *it; + + flags = obj->getAllTCPFlagMasks(); + for (it=flags.begin(); it!=flags.end(); ++it) flags_mask << *it; + return this; +} + +void* ObjectSignature::dispatch(UDPService *obj, void*) +{ + type_name = obj->getTypeName().c_str(); + src_port_range_start = obj->getSrcRangeStart(); + src_port_range_end = obj->getSrcRangeEnd(); + dst_port_range_start = obj->getDstRangeStart(); + dst_port_range_end = obj->getDstRangeEnd(); + return this; +} + +void* ObjectSignature::dispatch(CustomService *obj, void*) +{ + type_name = obj->getTypeName().c_str(); + platform = ""; + code = ""; + list platforms = obj->getAllKnownPlatforms(); + foreach(std::string pl, platforms) + { + platform += pl.c_str(); + code += obj->getCodeForPlatform(pl).c_str(); + } + protocol_name = obj->getProtocol().c_str(); + return this; +} + +void* ObjectSignature::dispatch(TagService *obj, void*) +{ + type_name = obj->getTypeName().c_str(); + tag = obj->getStr("tagcode").c_str(); + return this; +} + +/* + * Note that we do not track "compile time" / "run time" attribute of + * the object because on import, only "run time" make sense + */ +void* ObjectSignature::dispatch(DNSName *obj, void*) +{ + type_name = obj->getTypeName().c_str(); + dns_name = obj->getSourceName().c_str(); + return this; +} + + //**************************************************************** void ObjectMaker::clear() @@ -143,3 +298,30 @@ FWObject* ObjectMaker::createObject(FWObject *parent, o->setName(objName); return o; } + +//**************************************************************** + +/* + * scan the tree starting at @root and use registerObject to build + * signatures for all address and service objects in order to be able + * to use them on import + */ +void ObjectMaker::prepareForDeduplication(FWObject *root) +{ + if (RuleSet::cast(root) || Rule::cast(root) || + FWReference::cast(root) || + Host::cast(root) || + FWOptions::cast(root)) return; + + if (Address::cast(root) || Service::cast(root)) + { + ObjectSignature sig; + root->dispatch(&sig, (void*)(NULL)); + registerObject(sig, root); + } + + for (FWObject::iterator it=root->begin(); it!=root->end(); ++it) + { + prepareForDeduplication(*it); + } +} diff --git a/src/import/objectMaker.h b/src/import/objectMaker.h index f42623152..21102d3a9 100644 --- a/src/import/objectMaker.h +++ b/src/import/objectMaker.h @@ -26,6 +26,7 @@ #define _OBJECT_MAKER_H_ #include "fwbuilder/FWObject.h" +#include "fwbuilder/Dispatch.h" #include #include @@ -33,7 +34,23 @@ namespace libfwbuilder { + class AddressRange; + class Cluster; + class CustomService; + class Firewall; + class Host; + class ICMPService; + class IPService; + class IPv4; + class IPv6; + class Interface; class Library; + class Network; + class NetworkIPv6; + class TCPService; + class TagService; + class UDPService; + class physAddress; }; @@ -48,7 +65,7 @@ public: }; -class ObjectSignature +class ObjectSignature : public libfwbuilder::Dispatch { public: QString type_name; @@ -87,6 +104,25 @@ public: QString tag; QString toString() const; + + // The following methods build signature from given object taking + // into account its type + virtual void* dispatch(libfwbuilder::Network*, void*); + virtual void* dispatch(libfwbuilder::NetworkIPv6*, void*); + virtual void* dispatch(libfwbuilder::IPv4*, void*); + virtual void* dispatch(libfwbuilder::IPv6*, void*); + virtual void* dispatch(libfwbuilder::AddressRange*, void*); + virtual void* dispatch(libfwbuilder::AddressTable*, void*); + virtual void* dispatch(libfwbuilder::physAddress*, void*); + virtual void* dispatch(libfwbuilder::IPService*, void*); + virtual void* dispatch(libfwbuilder::ICMPService*, void*); + virtual void* dispatch(libfwbuilder::ICMP6Service*, void*); + virtual void* dispatch(libfwbuilder::TCPService*, void*); + virtual void* dispatch(libfwbuilder::UDPService*, void*); + virtual void* dispatch(libfwbuilder::CustomService*, void*); + virtual void* dispatch(libfwbuilder::TagService*, void*); + virtual void* dispatch(libfwbuilder::DNSName*, void*); + }; class ObjectMaker @@ -112,13 +148,10 @@ public: libfwbuilder::FWObject* createObject(libfwbuilder::FWObject *parent, const std::string &objType, const std::string &objName); - - void addStandardImportComment(libfwbuilder::FWObject *obj, - const QString &file_name, - int line_num); - libfwbuilder::FWObject *getLastCreatedObject() { return last_created; } + + void prepareForDeduplication(libfwbuilder::FWObject *root); }; diff --git a/src/libfwbuilder/src/fwbuilder/CustomService.cpp b/src/libfwbuilder/src/fwbuilder/CustomService.cpp index 08f04ce52..93a0362f8 100644 --- a/src/libfwbuilder/src/fwbuilder/CustomService.cpp +++ b/src/libfwbuilder/src/fwbuilder/CustomService.cpp @@ -184,6 +184,17 @@ const string CustomService::getCodeForPlatform(const string& platform) const return it->second; } +list CustomService::getAllKnownPlatforms() +{ + list res; + map::const_iterator i; + for (i=codes.begin(); i!=codes.end(); ++i) + { + res.push_back( (*i).first); + } + return res; +} + void CustomService::setProtocol(const string& proto) { protocol = proto; diff --git a/src/libfwbuilder/src/fwbuilder/CustomService.h b/src/libfwbuilder/src/fwbuilder/CustomService.h index a82d621ca..0c41e1817 100644 --- a/src/libfwbuilder/src/fwbuilder/CustomService.h +++ b/src/libfwbuilder/src/fwbuilder/CustomService.h @@ -79,7 +79,8 @@ class CustomService : public Service void setCodeForPlatform(const std::string& platform, const std::string& code); const std::string getCodeForPlatform(const std::string& platform) const; - + std::list getAllKnownPlatforms(); + void setProtocol(const std::string& proto); const std::string& getProtocol(); diff --git a/src/libgui/importFirewallConfigurationWizard/IC_FirewallNamePage.cpp b/src/libgui/importFirewallConfigurationWizard/IC_FirewallNamePage.cpp index f7042c006..534bf10d8 100644 --- a/src/libgui/importFirewallConfigurationWizard/IC_FirewallNamePage.cpp +++ b/src/libgui/importFirewallConfigurationWizard/IC_FirewallNamePage.cpp @@ -40,7 +40,10 @@ IC_FirewallNamePage::IC_FirewallNamePage(QWidget *parent) : QWizardPage(parent) m_dialog = new Ui::IC_FirewallNamePage_q; m_dialog->setupUi(this); + m_dialog->deduplicateOnImport->setChecked(true); + registerField("firewallName*", m_dialog->firewallName); + registerField("deduplicate", m_dialog->deduplicateOnImport); } void IC_FirewallNamePage::initializePage() diff --git a/src/libgui/importFirewallConfigurationWizard/IC_ProgressPage.cpp b/src/libgui/importFirewallConfigurationWizard/IC_ProgressPage.cpp index 998b6cfec..ff6334f29 100644 --- a/src/libgui/importFirewallConfigurationWizard/IC_ProgressPage.cpp +++ b/src/libgui/importFirewallConfigurationWizard/IC_ProgressPage.cpp @@ -135,6 +135,8 @@ void IC_ProgressPage::initializePage() dynamic_cast(wizard())-> getPlatform(); QString firewallName = field("firewallName").toString(); + bool deduplicate = field("deduplicate").toBool(); + QStringList *buffer = dynamic_cast(wizard())-> getBufferPtr(); @@ -142,9 +144,9 @@ void IC_ProgressPage::initializePage() importer = new ImporterThread(this, mw->getCurrentLib(), - *buffer, platform, firewallName, fileName); - - + *buffer, platform, firewallName, fileName, + deduplicate); + connect(importer, SIGNAL(destroyed(QObject*)), this, SLOT(importerDestroyed(QObject*))); connect(importer, SIGNAL(finished()), diff --git a/src/libgui/importFirewallConfigurationWizard/ImporterThread.cpp b/src/libgui/importFirewallConfigurationWizard/ImporterThread.cpp index 0ff78d0b6..1bd5e3ccd 100644 --- a/src/libgui/importFirewallConfigurationWizard/ImporterThread.cpp +++ b/src/libgui/importFirewallConfigurationWizard/ImporterThread.cpp @@ -53,7 +53,8 @@ ImporterThread::ImporterThread(QWidget *ui, const QStringList &buffer, const QString &platform, const QString &firewallName, - const QString &fileName) + const QString &fileName, + bool deduplicate) { this->lib = lib; this->ui = ui; @@ -61,6 +62,7 @@ ImporterThread::ImporterThread(QWidget *ui, this->platform = platform; this->firewallName = firewallName; this->fileName = fileName; + this->deduplicate = deduplicate; importer = NULL; stopFlag = false; } @@ -94,6 +96,7 @@ void ImporterThread::run() { importer->setFileName(fileName.toUtf8().constData()); + if (deduplicate) importer->prepareForDeduplication(); try { diff --git a/src/libgui/importFirewallConfigurationWizard/ImporterThread.h b/src/libgui/importFirewallConfigurationWizard/ImporterThread.h index 510478fcb..4ab33648c 100644 --- a/src/libgui/importFirewallConfigurationWizard/ImporterThread.h +++ b/src/libgui/importFirewallConfigurationWizard/ImporterThread.h @@ -50,6 +50,7 @@ class ImporterThread : public QThread QStringList buffer; QString firewallName; QString platform; + bool deduplicate; QWidget *ui; libfwbuilder::Firewall *fw; bool stopFlag; @@ -60,7 +61,8 @@ public: const QStringList &buffer, const QString &platform, const QString &firewallName, - const QString &fileName); + const QString &fileName, + bool deduplicate); virtual ~ImporterThread(); void run(); diff --git a/src/libgui/importFirewallConfigurationWizard/ic_firewallnamepage_q.ui b/src/libgui/importFirewallConfigurationWizard/ic_firewallnamepage_q.ui index 7e297f478..5a840aef6 100644 --- a/src/libgui/importFirewallConfigurationWizard/ic_firewallnamepage_q.ui +++ b/src/libgui/importFirewallConfigurationWizard/ic_firewallnamepage_q.ui @@ -16,8 +16,8 @@ Enter firewall object name - - + + Qt::Vertical @@ -33,7 +33,7 @@ - + @@ -60,7 +60,44 @@ - + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 40 + + + + + + + + + + The program can use objects that already exist in the "Standard Objects" library and user defined libraries to represent addresses and services found in the configuration being imported. This helps avoid duplicate objects. + + + true + + + + + + + Find and use existing objects + + + + + + Qt::Vertical