From 4ac2dd549b8e5576f19c05988a57a5bde79789cc Mon Sep 17 00:00:00 2001 From: Vadim Kurland Date: Thu, 19 Mar 2009 05:03:02 +0000 Subject: [PATCH] * iosacl.cpp (safetyNetInstall): fixed bug (no #): when "safety net install" option is used, temporary access list must be generated only once even when firewall object has multiple rulesets. ; --- build_num | 2 +- doc/ChangeLog | 5 + src/iosacl/PolicyCompiler_iosacl.cpp | 161 +--------------- src/iosacl/PolicyCompiler_iosacl.h | 3 +- src/iosacl/iosacl.cpp | 182 +++++++++++++++++++ test/iosacl/objects-for-regression-tests.fwb | 39 ++-- 6 files changed, 213 insertions(+), 179 deletions(-) diff --git a/build_num b/build_num index b448a949c..ce5e570e6 100644 --- a/build_num +++ b/build_num @@ -1 +1 @@ -#define BUILD_NUM 784 +#define BUILD_NUM 785 diff --git a/doc/ChangeLog b/doc/ChangeLog index 9ace4cdfa..74d70eaf6 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,10 @@ 2009-03-18 vadim + * iosacl.cpp (safetyNetInstall): fixed bug (no #): when "safety + net install" option is used, temporary access list must be + generated only once even when firewall object has multiple + rulesets. + * PolicyCompiler_iosacl.cpp (PolicyCompiler_iosacl::prolog): fixed bug (no #): temporary access list created for IOS when option "safety net install" is used and ipv6 address is provided should diff --git a/src/iosacl/PolicyCompiler_iosacl.cpp b/src/iosacl/PolicyCompiler_iosacl.cpp index cd13a02fe..dc22fe870 100644 --- a/src/iosacl/PolicyCompiler_iosacl.cpp +++ b/src/iosacl/PolicyCompiler_iosacl.cpp @@ -84,163 +84,6 @@ int PolicyCompiler_iosacl::prolog() output << "!################" << endl; - if ( fw->getOptionsObject()->getBool("iosacl_acl_substitution") ) - { - /* Generate short temporary ACL and assign it to all - * interfaces. This ACL permits IPSEC (IP proto 50 and UDP port 500) - as well as ssh from given subnet to any. - */ - - string temp_acl = "tmp_acl"; - string temp_acl_addr = fw->getOptionsObject()->getStr( - "iosacl_acl_temp_addr"); - - if (temp_acl_addr.empty()) - { - abort("Missing address for management host or subnet for temporary ACL.\nPlease enter it in the tab 'Script options' in 'Firewall Settings' dialog"); - } - - // if templ_acl_addr is ipv4 address, then we can not create this - // temporary ACL while compiling ipv6 policy. And vice versa. - - bool create_temp_acl = false; - if (temp_acl_addr.find(":")!=string::npos) - { - //looks like ipv6 - create_temp_acl = ipv6; - } else - { - // not ipv6, assume ipv4 - create_temp_acl = !ipv6; - } - - if (create_temp_acl) - { - string::size_type slash_idx = temp_acl_addr.find('/'); - string addr = temp_acl_addr; - string netmask = "255.255.255.255"; - bool tmp_acl_v6 = false; - - // check if addr is v6 - - try - { - InetAddr addrv6(AF_INET6, temp_acl_addr); - tmp_acl_v6 = true; - } catch(FWException &ex) - { - // Assume cnf->maddr is ipv4 - if (slash_idx!=string::npos) - { - addr = temp_acl_addr.substr(0,slash_idx); - netmask = temp_acl_addr.substr(slash_idx+1); - try - { - if (netmask.find(".")!=string::npos) - { - InetAddr nm(netmask); - nm.getLength(); // to avoid warning abt unused var - } else - { - int nm_length; - istringstream str(netmask); - str >> nm_length; - InetAddr nm(nm_length); - netmask = nm.toString(); - } - } catch(FWException &ex) - { - abort("Invalid netmask for management subnet: '"+netmask+"'"); - } - } - - try - { - InetAddr a(addr); - a.isAny(); - } catch(FWException &ex) - { - abort("Invalid address for management subnet: '"+addr+"'"); - } - } - - string xml_element = "clear_ip_acl"; - if (ipv6) xml_element = "clear_ipv6_acl"; - - string clearACLcmd = Resources::platform_res[platform]->getResourceStr( - string("/FWBuilderResources/Target/options/")+ - "version_"+version+"/iosacl_commands/" + xml_element); - - output << endl; - - string addr_family_prefix = "ip"; - - if (ipv6 && tmp_acl_v6) - { - addr_family_prefix = "ipv6"; - output << clearACLcmd << " " << temp_acl << endl; - output << "ipv6 access-list " << temp_acl << endl; - if (slash_idx!=string::npos) - output << " permit ipv6 " << addr << " any " << endl; - else - output << " permit ipv6 host " << addr << " any " << endl; - output << " deny ipv6 any any " << endl; - output << "exit" << endl; - output << endl; - } - - if (!ipv6 && !tmp_acl_v6) - { - // cisco uses "wildcards" instead of netmasks - - //long nm = InetAddr(netmask).to32BitInt(); - //struct in_addr na; - //na.s_addr = ~nm; - InetAddr nnm( ~(InetAddr(netmask)) ); - addr_family_prefix = "ip"; - output << clearACLcmd << " " << temp_acl << endl; - output << "ip access-list extended " << temp_acl << endl; - output << " permit ip " - << addr << " " << nnm.toString() << " any " << endl; - output << " deny ip any any " << endl; - output << "exit" << endl; - output << endl; - } - - - // find management interface - int nmi = 0; - list ll = fw->getByType(Interface::TYPENAME); - for (FWObject::iterator i=ll.begin(); i!=ll.end(); i++) - { - Interface *intf = Interface::cast( *i ); - if (intf->isManagement()) - { - nmi++; - output << "interface " << intf->getName() << endl; - output << " no " << addr_family_prefix << " "; - output << getAccessGroupCommandForAddressFamily(); - output << " in" << endl; - - output << " no " << addr_family_prefix << " "; - output << getAccessGroupCommandForAddressFamily(); - output << " out" << endl; - - output << " " << addr_family_prefix << " "; - output << getAccessGroupCommandForAddressFamily(); - output << " " << temp_acl << " in" << endl; - output << "exit" << endl; - } - } - if (nmi==0) - { - abort("One of the interfaces of the firewall must be marked as management interface."); - } - } - - output << endl; - } - return PolicyCompiler::prolog(); } @@ -467,7 +310,7 @@ string PolicyCompiler_iosacl::printAccessGroupCmd(ciscoACL *acl) str << "interface " << acl->getInterface()->getName() << endl; str << " " << addr_family_prefix << " "; - str << getAccessGroupCommandForAddressFamily(); + str << getAccessGroupCommandForAddressFamily(ipv6); str << " " << acl->workName() << " " << dir << endl; str << "exit" << endl; } @@ -492,7 +335,7 @@ void PolicyCompiler_iosacl::epilog() } } -string PolicyCompiler_iosacl::getAccessGroupCommandForAddressFamily() +string PolicyCompiler_iosacl::getAccessGroupCommandForAddressFamily(bool ipv6) { if (ipv6) return "traffic-filter"; return "access-group"; diff --git a/src/iosacl/PolicyCompiler_iosacl.h b/src/iosacl/PolicyCompiler_iosacl.h index f6b443da8..0941782e2 100644 --- a/src/iosacl/PolicyCompiler_iosacl.h +++ b/src/iosacl/PolicyCompiler_iosacl.h @@ -249,7 +249,6 @@ namespace fwcompiler { virtual std::string myPlatformName(); std::string printAccessGroupCmd(ciscoACL *acl); - std::string getAccessGroupCommandForAddressFamily(); public: @@ -263,6 +262,8 @@ namespace fwcompiler { virtual void compile(); virtual void epilog(); + static std::string getAccessGroupCommandForAddressFamily(bool ipv6); + }; diff --git a/src/iosacl/iosacl.cpp b/src/iosacl/iosacl.cpp index b8d639433..ce962a7f5 100644 --- a/src/iosacl/iosacl.cpp +++ b/src/iosacl/iosacl.cpp @@ -118,6 +118,185 @@ void usage(const char *name) cout << "Usage: " << name << " [-tvV] [-f filename.xml] [-d destdir] [-o output.fw] firewall_object_name" << endl; } +string safetyNetInstall(Firewall *fw) +{ + ostringstream output; + if ( fw->getOptionsObject()->getBool("iosacl_acl_substitution") ) + { + /* Generate short temporary ACL and assign it to all + * interfaces. This ACL permits IPSEC (IP proto 50 and UDP port 500) + as well as ssh from given subnet to any. + */ + + string platform = fw->getStr("platform"); + string version = fw->getStr("version"); + + string temp_acl = "tmp_acl"; + string temp_acl_addr = fw->getOptionsObject()->getStr( + "iosacl_acl_temp_addr"); + + if (temp_acl_addr.empty()) + { + cerr << "Missing address for management host or subnet for temporary ACL.\nPlease enter it in the tab 'Script options' in 'Firewall Settings' dialog" + << endl; + exit(-1); + } + + // if templ_acl_addr is ipv4 address, then we can not create this + // temporary ACL while compiling ipv6 policy. And vice versa. + + bool create_temp_acl = false; + bool tmp_acl_ipv6 = false; + if (temp_acl_addr.find(":")!=string::npos) + { + //looks like ipv6 + create_temp_acl = true; + tmp_acl_ipv6 = true; + } else + { + // not ipv6, assume ipv4 + create_temp_acl = true; + tmp_acl_ipv6 = false; + } + + if (create_temp_acl) + { + string::size_type slash_idx = temp_acl_addr.find('/'); + string addr = temp_acl_addr; + string netmask = "255.255.255.255"; + bool tmp_acl_v6 = false; + + // check if addr is v6 + + try + { + InetAddr addrv6(AF_INET6, temp_acl_addr); + tmp_acl_v6 = true; + } catch(FWException &ex) + { + // Assume cnf->maddr is ipv4 + if (slash_idx!=string::npos) + { + addr = temp_acl_addr.substr(0,slash_idx); + netmask = temp_acl_addr.substr(slash_idx+1); + try + { + if (netmask.find(".")!=string::npos) + { + InetAddr nm(netmask); + nm.getLength(); // to avoid warning abt unused var + } else + { + int nm_length; + istringstream str(netmask); + str >> nm_length; + InetAddr nm(nm_length); + netmask = nm.toString(); + } + } catch(FWException &ex) + { + cerr << "Invalid netmask for management subnet: '"+netmask+"'" + << endl; + exit(-1); + } + } + + try + { + InetAddr a(addr); + a.isAny(); + } catch(FWException &ex) + { + cerr << "Invalid address for management subnet: '"+addr+"'" + << endl; + exit(-1); + } + } + + string xml_element = "clear_ip_acl"; + if (tmp_acl_ipv6) xml_element = "clear_ipv6_acl"; + + string clearACLcmd = Resources::platform_res[platform]->getResourceStr( + string("/FWBuilderResources/Target/options/")+ + "version_"+version+"/iosacl_commands/" + xml_element); + + output << endl; + + string addr_family_prefix = "ip"; + + string access_group_cmd = + PolicyCompiler_iosacl::getAccessGroupCommandForAddressFamily(tmp_acl_v6); + + output << "! temporary access list for \"safety net install\"" + << endl; + output << endl; + + if (tmp_acl_v6) + { + addr_family_prefix = "ipv6"; + output << clearACLcmd << " " << temp_acl << endl; + output << "ipv6 access-list " << temp_acl << endl; + if (slash_idx!=string::npos) + output << " permit ipv6 " << addr << " any " << endl; + else + output << " permit ipv6 host " << addr << " any " << endl; + output << " deny ipv6 any any " << endl; + output << "exit" << endl; + output << endl; + } else + { + // cisco uses "wildcards" instead of netmasks + + //long nm = InetAddr(netmask).to32BitInt(); + //struct in_addr na; + //na.s_addr = ~nm; + InetAddr nnm( ~(InetAddr(netmask)) ); + addr_family_prefix = "ip"; + output << clearACLcmd << " " << temp_acl << endl; + output << "ip access-list extended " << temp_acl << endl; + output << " permit ip " + << addr << " " << nnm.toString() << " any " << endl; + output << " deny ip any any " << endl; + output << "exit" << endl; + output << endl; + } + + // find management interface + int nmi = 0; + list ll = fw->getByType(Interface::TYPENAME); + for (FWObject::iterator i=ll.begin(); i!=ll.end(); i++) + { + Interface *intf = Interface::cast( *i ); + if (intf->isManagement()) + { + nmi++; + output << "interface " << intf->getName() << endl; + output << " no " << addr_family_prefix << " "; + output << access_group_cmd; + output << " in" << endl; + + output << " no " << addr_family_prefix << " "; + output << access_group_cmd; + output << " out" << endl; + + output << " " << addr_family_prefix << " "; + output << access_group_cmd; + output << " " << temp_acl << " in" << endl; + output << "exit" << endl; + } + } + if (nmi==0) + { + cerr << "One of the interfaces of the firewall must be marked as management interface." + << endl; + exit(-1); + } + + output << endl; + } + } + return output.str(); +} int main(int argc, char * const * argv) { @@ -366,6 +545,9 @@ int main(int argc, char * const * argv) vector ipv4_6_runs; string generated_script; + generated_script = safetyNetInstall(fw); + + // 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/test/iosacl/objects-for-regression-tests.fwb b/test/iosacl/objects-for-regression-tests.fwb index 4d750ea35..9c6e9d31f 100644 --- a/test/iosacl/objects-for-regression-tests.fwb +++ b/test/iosacl/objects-for-regression-tests.fwb @@ -172,7 +172,7 @@ - + @@ -668,10 +668,10 @@ - + - - + + - + - + - + @@ -1046,7 +1046,7 @@ - + @@ -1503,17 +1503,19 @@ + - + - + - + + @@ -1547,6 +1549,7 @@ + @@ -2946,7 +2949,7 @@ - + @@ -3309,7 +3312,7 @@ - + @@ -3350,18 +3353,18 @@ - + - + - + - + @@ -3480,7 +3483,7 @@ - +