diff --git a/doc/ChangeLog b/doc/ChangeLog index a02cceda2..6cd39d358 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,13 @@ 2011-04-01 vadim + * PIXImporter.cpp (mirrorServiceObjectRecursively): see #2291 The + same service object-group that matches some tcp or udp ports can + be used to match both source and destination ports in an + access-list command. Importer should recognize when such group + is used to match source ports and create mirrored group with + potentially mirrored service objects. This should work when group + includes other groups. + * FWWindow_editor.cpp (openOptEditor): fixes #2307 "GUI switches to another file after editor panel is closed" diff --git a/src/import/PIXImporter.cpp b/src/import/PIXImporter.cpp index 20be24ce3..c87de8b72 100644 --- a/src/import/PIXImporter.cpp +++ b/src/import/PIXImporter.cpp @@ -46,8 +46,11 @@ #include "fwbuilder/Policy.h" #include "fwbuilder/RuleElement.h" #include "fwbuilder/Library.h" +#include "fwbuilder/ObjectMirror.h" #include "../libgui/platforms.h" +// TODO: FWBTree needs to be refactored into an independent module +#include "../libgui/FWBTree.h" #include #include @@ -198,6 +201,100 @@ FWObject* PIXImporter::makeSrvObj() return Importer::makeSrvObj(); } +/* + * See #2291 + * + * Service group can be defined to match dstination ports but used to + * match source ports in the access-list command. In ASA 8.0 and 8.3 the + * following configuration is valid: + * + * object-group service test-service-1 tcp + * port-object eq www + * + * Group test-service-1 can be used in the position in an access-list + * command where it would match source ports. + * + */ +void PIXImporter::fixServiceObjectUsedForSrcPorts() +{ + if ((protocol=="tcp" || protocol=="udp") && + named_objects_registry.count(src_port_spec.c_str()) > 0) + { + FWObject *obj = named_objects_registry[src_port_spec.c_str()]; + FWObject *new_obj = mirrorServiceObjectRecursively(obj); + src_port_spec = new_obj->getName(); + } +} + +FWObject* PIXImporter::mirrorServiceObjectRecursively(FWObject *obj) +{ + FWObject *res = NULL; + string new_name = obj->getName() + "-mirror"; + + if (Service::cast(obj) != NULL) + { + FWObject *new_obj = getMirroredServiceObject(obj); + + named_objects_registry[QString::fromUtf8(new_name.c_str())] = new_obj; + res = new_obj; + } else + { + // newObjectGroupService creates new group object, + // registers it as a named object and assigns pointer to + // it to current_object_group + newObjectGroupService(new_name); + + // if this group includes another group, we'll end up calling + // mirrorServiceObjectRecursively() again and at this very + // point will overwrite current_object_group with a pointer to + // that group's mirror + FWObject *new_group = current_object_group; + + for (FWObject::iterator it=obj->begin(); it!=obj->end(); ++it) + { + FWObject *new_obj = mirrorServiceObjectRecursively( + FWReference::getObject(*it)); + if (new_obj) + new_group->addRef(commitObject(new_obj)); + } + res = new_group; + current_object_group = new_group; + } + + return res; +} + +FWObject* PIXImporter::getMirroredServiceObject(FWObject *obj) +{ + string new_name = obj->getName() + "-mirror"; + QString qs_new_name = QString::fromUtf8(new_name.c_str()); + if (named_objects_registry.count(qs_new_name) > 0) + return named_objects_registry[qs_new_name]; + + Service *new_obj = NULL; + if (TCPService::isA(obj) || UDPService::isA(obj)) + { + ObjectMirror mirror; + new_obj = mirror.getMirroredService(Service::cast(obj)); + if (new_obj!=NULL) + { + new_obj->setName(new_name); + + // obj may belong to the standard objects library if it was + // deduplicated before + FWObject *parent = obj->getParent(); + if (parent->isReadOnly()) + { + FWBTree tree ; + FWObject *slot = tree.getStandardSlotForObject( + library, new_obj->getTypeName().c_str()); + slot->add(new_obj); + } else parent->add(new_obj); + } + } + return new_obj; +} + void PIXImporter::setInterfaceAndDirectionForRuleSet( const string &ruleset_name, const string &interface_label, const string &dir) { @@ -328,6 +425,10 @@ void PIXImporter::pushPolicyRule() rule->setDirection(PolicyRule::Both); + // named service object or a group can be defined to match dstination + // ports but used to match source ports in the access-list command. + fixServiceObjectUsedForSrcPorts(); + addSrc(); addDst(); addSrv(); diff --git a/src/import/PIXImporter.h b/src/import/PIXImporter.h index d9b82fa47..130d46708 100644 --- a/src/import/PIXImporter.h +++ b/src/import/PIXImporter.h @@ -68,7 +68,10 @@ public: class PIXImporter : public IOSImporter { - public: + libfwbuilder::FWObject* getMirroredServiceObject(libfwbuilder::FWObject *obj); + libfwbuilder::FWObject* mirrorServiceObjectRecursively(libfwbuilder::FWObject *obj); + +public: QString named_object_name; QString named_object_comment; @@ -133,6 +136,8 @@ class PIXImporter : public IOSImporter virtual libfwbuilder::FWObject* makeSrvObj(); virtual void addLogging(); + + void fixServiceObjectUsedForSrcPorts(); /* * the difference is that in PIX, we get interface label instead diff --git a/src/unit_tests/PIXImporterTest/test_data/asa8.3-acl.test b/src/unit_tests/PIXImporterTest/test_data/asa8.3-acl.test index ec1930bc9..22d690098 100755 --- a/src/unit_tests/PIXImporterTest/test_data/asa8.3-acl.test +++ b/src/unit_tests/PIXImporterTest/test_data/asa8.3-acl.test @@ -82,6 +82,12 @@ object service https.0 service tcp destination eq 443 exit +object service match-1 + service tcp destination eq 80 + +object service match-2 + service tcp destination lt 1024 + object network server-1.0 host 192.168.1.100 exit @@ -114,6 +120,21 @@ object-group network src-network-group-1 object-group network dst-network-group-1 network-object object external_net.0 +object-group service test-service-1 tcp + port-object eq www + +object-group service test-service-2 tcp + port-object range 1000 1010 + +object-group service test-service-3 tcp + port-object eq 25 + group-object test-service-1 + +object-group service test-service-4 tcp + port-object eq 25 + port-object eq 88 + group-object test-service-1 + !################ @@ -214,6 +235,21 @@ access-list outside_out standard permit 192.0.2.0 255.255.255.0 access-list outside_out standard permit host 192.0.2.1 access-list outside_out standard permit any +! test for access list using service group that matches destination port to match +! service port +access-list outside_in permit tcp object-group dst-network-group-1 object-group test-service-1 any +access-list outside_in permit tcp object-group dst-network-group-1 object-group test-service-2 any +access-list outside_in permit tcp object-group dst-network-group-1 object-group test-service-3 any +access-list outside_in permit tcp object-group dst-network-group-1 object-group test-service-4 any + + +! however named object can not be used to match source ports in ASA +! 8.3 so the following rules are invalid +! +! access-list outside_in permit tcp object-group dst-network-group-1 object match-1 any +! access-list outside_in permit tcp object-group dst-network-group-1 object match-2 any + + ! tests for access lists using object groups for both source service and destination address