From a59280a185305e2cf2fcfec829a8bccb2163aacb Mon Sep 17 00:00:00 2001 From: Vadim Kurland Date: Mon, 7 Jul 2008 02:32:38 +0000 Subject: [PATCH] support for ipv6 in fwb_iosacl; support for attribute ipv6 in RuleSet dialog --- doc/ChangeLog | 31 ++++ doc/fwb_iosacl.1 | 16 ++ doc/fwb_ipt.1 | 2 + src/cisco_lib/Helper.cpp | 10 +- src/cisco_lib/PolicyCompiler_cisco_acls.cpp | 41 ++++-- src/gui/RuleSetDialog.cpp | 3 + src/gui/iosaclAdvancedDialog.cpp | 12 +- src/gui/iosacladvanceddialog_q.ui | 9 +- src/gui/ipfAdvancedDialog.cpp | 1 - src/gui/ipfwAdvancedDialog.cpp | 1 - src/gui/ipfwadvanceddialog_q.ui | 11 +- src/gui/iptAdvancedDialog.cpp | 2 +- src/gui/iptadvanceddialog_q.ui | 11 +- src/gui/pfAdvancedDialog.cpp | 2 +- src/gui/pfadvanceddialog_q.ui | 11 +- src/gui/pixAdvancedDialog.cpp | 2 - src/gui/pixadvanceddialog_q.ui | 15 +- src/gui/rulesetdialog_q.ui | 146 ++++++++++--------- src/iosacl/PolicyCompiler_iosacl.cpp | 44 ++++-- src/iosacl/PolicyCompiler_iosacl.h | 1 + src/iosacl/PolicyCompiler_iosacl_writers.cpp | 73 ++++++---- src/iosacl/iosacl.cpp | 123 ++++++++++++---- src/ipt/ipt.cpp | 42 ++++-- src/pf/pf.cpp | 12 +- 24 files changed, 399 insertions(+), 222 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index 3c2def81a..a276e21cc 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,36 @@ 2008-07-06 Vadim Kurland + * PolicyCompiler_iosacl_writers.cpp (PrintRule::_printAddr): + Support for IPv6 in Cisco IOS ACL compiler fwb_iosacl. + + * iptAdvancedDialog.cpp (iptAdvancedDialog::iptAdvancedDialog): + Removed option "Enable IPv6 support" in the "advanced" dialog for + all platforms. Now user needs to explicitly declare rule sets as + ipv6. Since by default all rule sets are ipv4, there is no need + in yet another parameter to enable ipv6 support. + + * RuleSetDialog.cpp (RuleSetDialog::applyChanges): Objects Policy, + NAT and Routing now have attribute that tells compiler that + corresponding rule set is ipv4 or ipv6. The attribute is + controlled by radio-buttons in corresponding object dialog. Every + policy or nat rule set is treated as exclusively either ipv4 or + ipv6 by compilers, however the user can put objects of both + address families in rules. This allows for creation of object + groups that include objects of both address families. Such groups + can be used in both ipv4 and ipv6 rule sets. Compilers pick + objects that match address family declared for the rule set and drop + others. + + One of the reasons why this attribute was added is to avoid + generation of unwanted iptables or acl lines for rules that can + not be unambiguously attributed to particular address + family. Example of such rule is rule with "any" in both source and + destination (e.g. "catch all and deny" rule typically found at the + bottom of the policy). Without this attribute compilers tried to + process every rule set for both ipv4 and ipv6. This way rule "any + any any deny" found in ipv4 policy yielded corresponding line in + the ipv6 policy, which was wrong. + * instDialog.cpp (instDialog::installSelected): minor fixed in installer dialog (fixed progress bar and buffering of the compiler output) diff --git a/doc/fwb_iosacl.1 b/doc/fwb_iosacl.1 index d02c0c3eb..475069eff 100644 --- a/doc/fwb_iosacl.1 +++ b/doc/fwb_iosacl.1 @@ -10,6 +10,8 @@ fwb_ipt \- Policy compiler for Cisco IOS ACL .B fwb_iosacl .B [-vV] .B [-d wdir] +.B [-4] +.B [-6] .B -f data_file.xml object_name @@ -32,6 +34,20 @@ The data file and the name of the firewall objects must be specified on the command line. Other command line parameters are optional. .SH OPTIONS + +.IP "-4" +Generate iptables script for IPv4 part of the policy. If any rules of +the firewall refer to IPv6 addresses, compiler will skip these rules. +Options "-4" and "-6" are exclusive. If neither option is used, compiler +tries to generate both parts of the script, although generation of +the IPv6 part is controlled by the option "Enable IPv6 support" +in the "IPv6" tab of the firewall object advanced settings dialog. +This option is off by default. + +.IP "-6" +Generate iptables script for IPv6 part of the policy. If any rules of +the firewall refer to IPv6 addresses, compiler will skip these rules. + .IP "-f FILE" Specify the name of the data file to be processed. diff --git a/doc/fwb_ipt.1 b/doc/fwb_ipt.1 index 16ddce8dc..7d6d7d33d 100644 --- a/doc/fwb_ipt.1 +++ b/doc/fwb_ipt.1 @@ -7,6 +7,8 @@ fwb_ipt \- Policy compiler for iptables .RB [-wvV] .RB [-d wdir] .RB [-o output.fw] +.RB [-4] +.RB [-6] .RB -f data_file.xml object_name diff --git a/src/cisco_lib/Helper.cpp b/src/cisco_lib/Helper.cpp index d5ae1fe8f..6ea6215ac 100644 --- a/src/cisco_lib/Helper.cpp +++ b/src/cisco_lib/Helper.cpp @@ -33,9 +33,11 @@ #include #include #include "fwbuilder/Resources.h" +#include #include #include +#include using namespace libfwbuilder; using namespace fwcompiler; @@ -112,7 +114,13 @@ int Helper::findInterfaceByAddress(const InetAddr *addr) for (list::iterator i=l2.begin(); i!=l2.end(); ++i) { Interface *iface=Interface::cast(*i); - if ( iface->belongs( *addr ) ) return iface->getId(); + FWObjectTypedChildIterator j = + iface->findByType((addr->isV4())?IPv4::TYPENAME:IPv6::TYPENAME); + for (; j!=j.end(); ++j) + { + const Address *i_addr = Address::constcast(*j); + if ( i_addr->belongs(*addr) ) return iface->getId(); + } } return -1; } diff --git a/src/cisco_lib/PolicyCompiler_cisco_acls.cpp b/src/cisco_lib/PolicyCompiler_cisco_acls.cpp index 8b5798a86..a532daa8d 100644 --- a/src/cisco_lib/PolicyCompiler_cisco_acls.cpp +++ b/src/cisco_lib/PolicyCompiler_cisco_acls.cpp @@ -87,7 +87,8 @@ bool PolicyCompiler_cisco::setInterfaceAndDirectionBySrc::processNext() assert(ifs); if (ifs->isUnprotected()) continue; // skip! - PolicyRule *new_rule= PolicyRule::cast(compiler->dbcopy->create(PolicyRule::TYPENAME) ); + PolicyRule *new_rule = PolicyRule::cast( + compiler->dbcopy->create(PolicyRule::TYPENAME) ); compiler->temp_ruleset->add(new_rule); new_rule->duplicate(rule); new_rule->setInterfaceId(intf_id); @@ -128,7 +129,9 @@ bool PolicyCompiler_cisco::setInterfaceAndDirectionByDst::processNext() if (rule->getDirection()==PolicyRule::Outbound) intf_id_list = helper.getAllInterfaceIDs(); - for (list::iterator i = intf_id_list.begin(); i!=intf_id_list.end(); ++i) + + for (list::iterator i = intf_id_list.begin(); + i!=intf_id_list.end(); ++i) { int intf_id = *i; Interface *ifs = Interface::cast( @@ -136,7 +139,8 @@ bool PolicyCompiler_cisco::setInterfaceAndDirectionByDst::processNext() assert(ifs); if (ifs->isUnprotected()) continue; // skip! - PolicyRule *new_rule= PolicyRule::cast(compiler->dbcopy->create(PolicyRule::TYPENAME) ); + PolicyRule *new_rule = PolicyRule::cast( + compiler->dbcopy->create(PolicyRule::TYPENAME) ); compiler->temp_ruleset->add(new_rule); new_rule->duplicate(rule); new_rule->setInterfaceId(intf_id); @@ -173,7 +177,7 @@ bool PolicyCompiler_cisco::setInterfaceAndDirectionIfInterfaceSet::processNext() if (rule->getDirection()==PolicyRule::Both) { new_rule = - PolicyRule::cast(compiler->dbcopy->create(PolicyRule::TYPENAME) ); + PolicyRule::cast(compiler->dbcopy->create(PolicyRule::TYPENAME)); compiler->temp_ruleset->add(new_rule); new_rule->duplicate(rule); new_rule->setInterfaceId( rule_iface_id ); @@ -182,7 +186,7 @@ bool PolicyCompiler_cisco::setInterfaceAndDirectionIfInterfaceSet::processNext() tmp_queue.push_back(new_rule); new_rule = - PolicyRule::cast(compiler->dbcopy->create(PolicyRule::TYPENAME) ); + PolicyRule::cast(compiler->dbcopy->create(PolicyRule::TYPENAME)); compiler->temp_ruleset->add(new_rule); new_rule->duplicate(rule); new_rule->setInterfaceId( rule_iface_id ); @@ -192,7 +196,7 @@ bool PolicyCompiler_cisco::setInterfaceAndDirectionIfInterfaceSet::processNext() } else { new_rule = - PolicyRule::cast(compiler->dbcopy->create(PolicyRule::TYPENAME) ); + PolicyRule::cast(compiler->dbcopy->create(PolicyRule::TYPENAME)); compiler->temp_ruleset->add(new_rule); new_rule->duplicate(rule); new_rule->setInterfaceId( rule_iface_id ); @@ -206,13 +210,16 @@ bool PolicyCompiler_cisco::setInterfaceAndDirectionIfInterfaceSet::processNext() bool PolicyCompiler_cisco::pickACL::processNext() { - PolicyCompiler_cisco *cisco_comp=dynamic_cast(compiler); + PolicyCompiler_cisco *cisco_comp=dynamic_cast( + compiler); PolicyRule *rule=getNext(); if (rule==NULL) return false; - Interface *rule_iface = compiler->getCachedFwInterface(rule->getInterfaceId()); + Interface *rule_iface = compiler->getCachedFwInterface( + rule->getInterfaceId()); if(rule_iface==NULL) { - compiler->abort("Missing interface assignment for rule "+rule->getLabel()); + compiler->abort("Missing interface assignment for rule " + + rule->getLabel()); } /* @@ -248,8 +255,17 @@ bool PolicyCompiler_cisco::pickACL::processNext() if (acl_name.empty()) acl_name = rule_iface->getName(); acl_name = cisco_comp->mangleInterfaceName(acl_name) + "_acl"; string dir = "in"; - if (rule->getDirection() == PolicyRule::Inbound) { acl_name += "_in"; dir="in"; } - if (rule->getDirection() == PolicyRule::Outbound) { acl_name += "_out"; dir="out"; } + if (rule->getDirection() == PolicyRule::Inbound) + { + acl_name += "_in"; dir="in"; + } + if (rule->getDirection() == PolicyRule::Outbound) + { + acl_name += "_out"; dir="out"; + } + + if (cisco_comp->ipv6) acl_name = "ipv6_" + acl_name; + rule->setStr("acl",acl_name); ciscoACL *acl = new ciscoACL(acl_name, rule_iface, dir, using_named_acl); @@ -267,7 +283,8 @@ bool PolicyCompiler_cisco::pickACL::processNext() * in a human-readable way. */ -std::string PolicyCompiler_cisco::mangleInterfaceName(const string &interface_name) +std::string PolicyCompiler_cisco::mangleInterfaceName( + const string &interface_name) { string::size_type n; string s = interface_name; diff --git a/src/gui/RuleSetDialog.cpp b/src/gui/RuleSetDialog.cpp index c76419d02..d2704cc2c 100644 --- a/src/gui/RuleSetDialog.cpp +++ b/src/gui/RuleSetDialog.cpp @@ -75,6 +75,8 @@ void RuleSetDialog::loadFWObject(FWObject *o) m_dialog->obj_name->setText( QString::fromUtf8(s->getName().c_str()) ); m_dialog->comment->setText( QString::fromUtf8(s->getComment().c_str()) ); + m_dialog->ipv4_rule_set->setChecked(!s->isV6()); + m_dialog->ipv6_rule_set->setChecked(s->isV6()); init=false; } @@ -120,6 +122,7 @@ void RuleSetDialog::applyChanges() string oldname=obj->getName(); obj->setName( string(m_dialog->obj_name->text().toUtf8().constData()) ); obj->setComment( string(m_dialog->comment->toPlainText().toUtf8().constData()) ); + s->setV6(m_dialog->ipv6_rule_set->isChecked()); mw->updateObjName(obj,QString::fromUtf8(oldname.c_str())); diff --git a/src/gui/iosaclAdvancedDialog.cpp b/src/gui/iosaclAdvancedDialog.cpp index bb8688522..20fab1a66 100644 --- a/src/gui/iosaclAdvancedDialog.cpp +++ b/src/gui/iosaclAdvancedDialog.cpp @@ -225,11 +225,13 @@ iosaclAdvancedDialog::iosaclAdvancedDialog(QWidget *parent,FWObject *o) Management *mgmt=(Firewall::cast(obj))->getManagementObject(); assert(mgmt!=NULL); - m_dialog->notebook304->setTabEnabled(5,false); //Disable tab - data.registerOption(m_dialog->ipv4before_2, fwoptions, "ipv4_6_order", QStringList() << "IPv4 before IPv6" <<"ipv4_first" << "IPv6 before IPv4" << "ipv6_first" ); - data.registerOption(m_dialog->ipv6_2, fwoptions, "enable_ipv6" ); - - + data.registerOption(m_dialog->ipv4before_2, fwoptions, + "ipv4_6_order", + QStringList() << "IPv4 before IPv6" + << "ipv4_first" + << "IPv6 before IPv4" + << "ipv6_first" + ); /* Page "Compiler Options" */ data.registerOption( m_dialog->outputFileName , fwoptions, diff --git a/src/gui/iosacladvanceddialog_q.ui b/src/gui/iosacladvanceddialog_q.ui index 91c543763..d30928d5c 100644 --- a/src/gui/iosacladvanceddialog_q.ui +++ b/src/gui/iosacladvanceddialog_q.ui @@ -118,7 +118,7 @@ - 0 + 5 @@ -1215,13 +1215,6 @@ First, create temporary access list to permit connections from the management su IPv6 - - - - Enable IPv6 support - - - diff --git a/src/gui/ipfAdvancedDialog.cpp b/src/gui/ipfAdvancedDialog.cpp index da2c80baf..5b692d043 100644 --- a/src/gui/ipfAdvancedDialog.cpp +++ b/src/gui/ipfAdvancedDialog.cpp @@ -81,7 +81,6 @@ ipfAdvancedDialog::ipfAdvancedDialog(QWidget *parent,FWObject *o) m_dialog->tabWidget3->setTabEnabled(6,false); //Disable tab data.registerOption(m_dialog->ipv4before_2, fwopt, "ipv4_6_order", QStringList() << "IPv4 before IPv6" <<"ipv4_first" << "IPv6 before IPv4" << "ipv6_first" ); - data.registerOption(m_dialog->ipv6_2, fwopt, "enable_ipv6" ); data.registerOption( m_dialog->ipf_log_or_block ,fwopt, "ipf_log_or_block" ); data.registerOption( m_dialog->ipf_log_body ,fwopt, "ipf_log_body" ); data.registerOption( m_dialog->ipf_check_shadowing ,fwopt, "check_shading" ); diff --git a/src/gui/ipfwAdvancedDialog.cpp b/src/gui/ipfwAdvancedDialog.cpp index 2736763d9..326693e28 100644 --- a/src/gui/ipfwAdvancedDialog.cpp +++ b/src/gui/ipfwAdvancedDialog.cpp @@ -82,7 +82,6 @@ ipfwAdvancedDialog::ipfwAdvancedDialog(QWidget *parent,FWObject *o) m_dialog->tabWidget3->setTabEnabled(4,false); //Disable tab data.registerOption(m_dialog->ipv4before_2, fwopt, "ipv4_6_order", QStringList() << "IPv4 before IPv6" <<"ipv4_first" << "IPv6 before IPv4" << "ipv6_first" ); - data.registerOption(m_dialog->ipv6_2, fwopt, "enable_ipv6" ); data.registerOption( m_dialog->ipfw_add_check_state_rule ,fwopt, "add_check_state_rule"); data.registerOption( m_dialog->ipfw_check_shadowing ,fwopt, "check_shading" ); diff --git a/src/gui/ipfwadvanceddialog_q.ui b/src/gui/ipfwadvanceddialog_q.ui index 76a9e35b5..57cf25e89 100644 --- a/src/gui/ipfwadvanceddialog_q.ui +++ b/src/gui/ipfwadvanceddialog_q.ui @@ -5,7 +5,7 @@ 0 0 - 624 + 691 571 @@ -101,7 +101,7 @@ - 0 + 4 @@ -881,13 +881,6 @@ with this address: IPv6 - - - - Enable IPv6 support - - - diff --git a/src/gui/iptAdvancedDialog.cpp b/src/gui/iptAdvancedDialog.cpp index 0057357d5..25f385e10 100644 --- a/src/gui/iptAdvancedDialog.cpp +++ b/src/gui/iptAdvancedDialog.cpp @@ -80,7 +80,7 @@ iptAdvancedDialog::iptAdvancedDialog(QWidget *parent,FWObject *o) //QString s = fwoptions->getStr("ipv4_6_order") data.registerOption(m_dialog->ipv4before, fwoptions, "ipv4_6_order", QStringList() << "IPv4 before IPv6" <<"ipv4_first" << "IPv6 before IPv4" << "ipv6_first" ); - data.registerOption(m_dialog->ipv6, fwoptions, "enable_ipv6" ); + data.registerOption(m_dialog->logTCPseq, fwoptions, "log_tcp_seq" ); data.registerOption(m_dialog->logTCPopt, fwoptions, "log_tcp_opt" ); data.registerOption(m_dialog->logIPopt, fwoptions, "log_ip_opt" ); diff --git a/src/gui/iptadvanceddialog_q.ui b/src/gui/iptadvanceddialog_q.ui index a24776487..6e3f2211b 100644 --- a/src/gui/iptadvanceddialog_q.ui +++ b/src/gui/iptadvanceddialog_q.ui @@ -8,7 +8,7 @@ 0 0 - 677 + 687 719 @@ -49,7 +49,7 @@ - 0 + 5 @@ -1364,13 +1364,6 @@ with this address: IPv6 - - - - Enable IPv6 support - - - diff --git a/src/gui/pfAdvancedDialog.cpp b/src/gui/pfAdvancedDialog.cpp index 7e79b518d..e8c5fb650 100644 --- a/src/gui/pfAdvancedDialog.cpp +++ b/src/gui/pfAdvancedDialog.cpp @@ -73,7 +73,7 @@ pfAdvancedDialog::pfAdvancedDialog(QWidget *parent,FWObject *o) fwopt->setStr("firewall_dir",""); } data.registerOption(m_dialog->ipv4before, fwopt, "ipv4_6_order", QStringList() << "IPv4 before IPv6" <<"ipv4_first" << "IPv6 before IPv4" << "ipv6_first" ); - data.registerOption(m_dialog->ipv6, fwopt, "enable_ipv6" ); + data.registerOption( m_dialog->pf_log_prefix ,fwopt, "log_prefix" ); data.registerOption( m_dialog->pf_fallback_log ,fwopt, "fallback_log" ); data.registerOption( m_dialog->pf_do_timeout_interval,fwopt,"pf_do_timeout_interval"); diff --git a/src/gui/pfadvanceddialog_q.ui b/src/gui/pfadvanceddialog_q.ui index fa8e7d574..3a2190db9 100644 --- a/src/gui/pfadvanceddialog_q.ui +++ b/src/gui/pfadvanceddialog_q.ui @@ -5,7 +5,7 @@ 0 0 - 679 + 691 662 @@ -80,7 +80,7 @@ - 0 + 8 @@ -2378,13 +2378,6 @@ with this address: IPv6 - - - - Enable IPv6 support - - - diff --git a/src/gui/pixAdvancedDialog.cpp b/src/gui/pixAdvancedDialog.cpp index b45d3e3e4..5b0be9a02 100644 --- a/src/gui/pixAdvancedDialog.cpp +++ b/src/gui/pixAdvancedDialog.cpp @@ -243,8 +243,6 @@ pixAdvancedDialog::pixAdvancedDialog(QWidget*, FWObject *o)//(parent) m_dialog->notebook304->setTabEnabled(8,false); //Disable tab data.registerOption(m_dialog->ipv4before_2, fwoptions, "ipv4_6_order", QStringList() << "IPv4 before IPv6" <<"ipv4_first" << "IPv6 before IPv4" << "ipv6_first" ); - data.registerOption(m_dialog->ipv6_2, fwoptions, "enable_ipv6" ); - data.registerOption( m_dialog->outputFileName , fwoptions, diff --git a/src/gui/pixadvanceddialog_q.ui b/src/gui/pixadvanceddialog_q.ui index 0444319a1..80bc814f3 100644 --- a/src/gui/pixadvanceddialog_q.ui +++ b/src/gui/pixadvanceddialog_q.ui @@ -8,8 +8,8 @@ 0 0 - 1106 - 719 + 691 + 713 @@ -82,7 +82,7 @@ - 0 + 8 @@ -4505,16 +4505,9 @@ the packet should go to, and which is the next hop - Page + IPv6 - - - - Enable IPv6 support - - - diff --git a/src/gui/rulesetdialog_q.ui b/src/gui/rulesetdialog_q.ui index 7a130b2d3..b93303685 100644 --- a/src/gui/rulesetdialog_q.ui +++ b/src/gui/rulesetdialog_q.ui @@ -8,8 +8,8 @@ 0 0 - 563 - 146 + 660 + 209 @@ -131,24 +131,16 @@ QFrame::Sunken - - 2 - - - 2 - - - 2 - - - 2 - - - 8 - - - 2 - + + + + Comment: + + + false + + + @@ -158,40 +150,6 @@ QFrame::Sunken - - 8 - - - 8 - - - 8 - - - 8 - - - 2 - - - 8 - - - - - Qt::Vertical - - - QSizePolicy::MinimumExpanding - - - - 20 - 5 - - - - @@ -218,6 +176,36 @@ + + + + This is IPv4 rule set + + + + + + + This is IPv6 rule set + + + + + + + Qt::Vertical + + + QSizePolicy::MinimumExpanding + + + + 127 + 21 + + + + @@ -240,16 +228,6 @@ - - - - Comment: - - - false - - - @@ -271,8 +249,8 @@ changed() - 20 - 20 + 89 + 98 20 @@ -287,8 +265,8 @@ changed() - 20 - 20 + 238 + 87 20 @@ -296,5 +274,37 @@ + + ipv4_rule_set + toggled(bool) + RuleSetDialog_q + changed() + + + 110 + 118 + + + 329 + 104 + + + + + ipv6_rule_set + toggled(bool) + RuleSetDialog_q + changed() + + + 110 + 142 + + + 329 + 104 + + + diff --git a/src/iosacl/PolicyCompiler_iosacl.cpp b/src/iosacl/PolicyCompiler_iosacl.cpp index 9d5efee72..01bca6d51 100644 --- a/src/iosacl/PolicyCompiler_iosacl.cpp +++ b/src/iosacl/PolicyCompiler_iosacl.cpp @@ -149,10 +149,16 @@ int PolicyCompiler_iosacl::prolog() //na.s_addr = ~nm; InetAddr nnm( ~(InetAddr(netmask)) ); + string addr_family_prefix = "ip"; + if (ipv6) addr_family_prefix = "ipv6"; + 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 << addr_family_prefix + << " access-list extended " << temp_acl << endl; + output << " permit ip " + << addr << " " << nnm.toString() << " any " << endl; + output << " deny " << addr_family_prefix + << " any any " << endl; output << "exit" << endl; output << endl; @@ -166,9 +172,12 @@ int PolicyCompiler_iosacl::prolog() { nmi++; output << "interface " << intf->getName() << endl; - output << " no ip access-group in" << endl; - output << " no ip access-group out" << endl; - output << " ip access-group " << temp_acl << " in" << endl; + output << " no " << addr_family_prefix + << " access-group in" << endl; + output << " no " << addr_family_prefix + << " access-group out" << endl; + output << " " << addr_family_prefix + << " access-group " << temp_acl << " in" << endl; output << "exit" << endl; } } @@ -238,7 +247,10 @@ bool PolicyCompiler_iosacl::SpecialServices::processNext() void PolicyCompiler_iosacl::compile() { - cout << " Compiling policy for " << fw->getName() << " ..." << endl << flush; + cout << endl; + cout << " Compiling ruleset " << getRuleSetName(); + if (ipv6) cout << ", IPv6"; + cout << endl << flush; try { @@ -251,10 +263,10 @@ void PolicyCompiler_iosacl::compile() if ( fw->getOptionsObject()->getBool ("check_shading") ) { - add( new Begin ("Detecting rule shadowing" ) ); - add( new printTotalNumberOfRules ( ) ); + add( new Begin("Detecting rule shadowing" ) ); + add( new printTotalNumberOfRules()); - add( new ItfNegation( "process negation in Itf" ) ); + add( new ItfNegation("process negation in Itf" ) ); add( new InterfacePolicyRules( "process interface policy rules and store interface ids")); @@ -262,7 +274,9 @@ void PolicyCompiler_iosacl::compile() add( new recursiveGroupsInDst("check for recursive groups in DST")); add( new recursiveGroupsInSrv("check for recursive groups in SRV")); - add( new ExpandGroups ("expand groups")); + add( new ExpandGroups("expand groups")); + add( new dropRuleWithEmptyRE( + "drop rules with empty rule elements")); add( new eliminateDuplicatesInSRC("eliminate duplicates in SRC")); add( new eliminateDuplicatesInDST("eliminate duplicates in DST")); add( new eliminateDuplicatesInSRV("eliminate duplicates in SRV")); @@ -270,6 +284,8 @@ void PolicyCompiler_iosacl::compile() "expand objects with multiple addresses in SRC" ) ); add( new ExpandMultipleAddressesInDST( "expand objects with multiple addresses in DST" ) ); + add( new dropRuleWithEmptyRE( + "drop rules with empty rule elements")); add( new ConvertToAtomic("convert to atomic rules" ) ); add( new DetectShadowing("Detect shadowing" ) ); add( new simplePrintProgress() ); @@ -291,6 +307,8 @@ void PolicyCompiler_iosacl::compile() add( new emptyGroupsInSrv( "check for empty groups in SRV" ) ); add( new ExpandGroups ("expand groups" ) ); + add( new dropRuleWithEmptyRE( + "drop rules with empty rule elements")); add( new eliminateDuplicatesInSRC( "eliminate duplicates in SRC" ) ); add( new eliminateDuplicatesInDST( "eliminate duplicates in DST" ) ); add( new eliminateDuplicatesInSRV( "eliminate duplicates in SRV" ) ); @@ -316,12 +334,16 @@ void PolicyCompiler_iosacl::compile() "expand objects with multiple addresses in DST" ) ); add( new MACFiltering( "check for MAC address filtering" ) ); + add( new dropRuleWithEmptyRE( + "drop rules with empty rule elements")); // add( new splitByNetworkZonesForDst ("split rule if objects in Dst belong to different network zones " ) ); add( new checkForUnnumbered( "check for unnumbered interfaces" ) ); add( new addressRanges ("process address ranges" ) ); + add( new dropRuleWithEmptyRE( + "drop rules with empty rule elements")); add( new setInterfaceAndDirectionBySrc( "Set interface and direction for rules with interface 'all' using SRC")); diff --git a/src/iosacl/PolicyCompiler_iosacl.h b/src/iosacl/PolicyCompiler_iosacl.h index dcdfd844f..96826550f 100644 --- a/src/iosacl/PolicyCompiler_iosacl.h +++ b/src/iosacl/PolicyCompiler_iosacl.h @@ -191,6 +191,7 @@ namespace fwcompiler { std::string _printSrcService(libfwbuilder::Service *srv); std::string _printDstService(libfwbuilder::Service *srv); std::string _printAddr(libfwbuilder::Address *o); + std::string _printProtocol(libfwbuilder::Service *srv); std::string _printAction(libfwbuilder::PolicyRule *r); std::string _printACL(libfwbuilder::PolicyRule *r); std::string _printLog(libfwbuilder::PolicyRule *r); diff --git a/src/iosacl/PolicyCompiler_iosacl_writers.cpp b/src/iosacl/PolicyCompiler_iosacl_writers.cpp index 0cb3cebb6..8cb175321 100644 --- a/src/iosacl/PolicyCompiler_iosacl_writers.cpp +++ b/src/iosacl/PolicyCompiler_iosacl_writers.cpp @@ -38,6 +38,7 @@ #include "fwbuilder/FWObjectDatabase.h" #include "fwbuilder/Interface.h" #include "fwbuilder/IPv4.h" +#include "fwbuilder/IPv6.h" #include "fwbuilder/Network.h" #include "fwbuilder/Management.h" #include "fwbuilder/Resources.h" @@ -156,13 +157,19 @@ bool PolicyCompiler_iosacl::PrintCompleteACLs::processNext() compiler->output << endl; } + string addr_family_prefix = "ip"; + if (iosacl_comp->ipv6) addr_family_prefix = "ipv6"; + for (map::iterator i=iosacl_comp->acls.begin(); i!=iosacl_comp->acls.end(); ++i) { ciscoACL *acl=(*i).second; - compiler->output << "ip access-list extended " << acl->workName() << endl; + compiler->output << addr_family_prefix + << " access-list extended " + << acl->workName() << endl; std::for_each(tmp_queue.begin(), tmp_queue.end(), - printRulesForACL(iosacl_comp, this, acl, &(compiler->output))); + printRulesForACL(iosacl_comp, + this, acl, &(compiler->output))); compiler->output << "exit" << endl; compiler->output << endl; } @@ -253,8 +260,7 @@ string PolicyCompiler_iosacl::PrintRule::_printRule(PolicyRule *rule) aclstr << _printAction(rule); - aclstr << Service::cast(srvobj)->getProtocolName(); - aclstr << " "; + aclstr << _printProtocol(Service::cast(srvobj)); aclstr << _printAddr( compiler->getFirstSrc(rule) ); aclstr << _printSrcService( compiler->getFirstSrv(rule) ); aclstr << _printAddr( compiler->getFirstDst(rule) ); @@ -383,8 +389,21 @@ string PolicyCompiler_iosacl::PrintRule::_printDstService(Service *srv) return str.str(); } -string PolicyCompiler_iosacl::PrintRule::_printAddr(libfwbuilder::Address *o) +string PolicyCompiler_iosacl::PrintRule::_printProtocol(Service *srv) { + PolicyCompiler_iosacl *iosacl_comp = dynamic_cast( + compiler); + string addr_family_prefix = "ip "; + if (iosacl_comp->ipv6) addr_family_prefix = "ipv6 "; + + string proto = srv->getProtocolName(); + if (proto=="ip") return addr_family_prefix; + return proto + " "; +} + +string PolicyCompiler_iosacl::PrintRule::_printAddr(Address *o) +{ + PolicyCompiler_iosacl *iosacl_comp=dynamic_cast(compiler); if (Interface::cast(o)!=NULL) { Interface *interface_=Interface::cast(o); @@ -399,33 +418,35 @@ string PolicyCompiler_iosacl::PrintRule::_printAddr(libfwbuilder::Address *o) const InetAddr *srcaddr = o->getAddressPtr(); if (srcaddr) { - InetAddr srcmask = *(o->getNetmaskPtr()); - - if (Interface::cast(o)!=NULL) - srcmask = InetAddr(InetAddr::getAllOnes()); - - if (IPv4::cast(o)!=NULL) - srcmask = InetAddr(InetAddr::getAllOnes()); + const InetAddr srcmask = *(o->getNetmaskPtr()); if (srcaddr->isAny() && srcmask.isAny()) { - str << "any "; - } else { - if (srcmask.isHostMask()) + str << "any "; + } else + { + if (Interface::cast(o)==NULL && + Interface::cast(o->getParent())==NULL && + !srcmask.isHostMask()) { - str << "host " << srcaddr->toString() << " "; + if (iosacl_comp->ipv6) + { + str << srcaddr->toString() + << "/" + << srcmask.getLength() << " "; + } else + { + str << srcaddr->toString() << " "; + // cisco uses "wildcards" instead of netmasks + //long nm = srcmask.to32BitInt(); + //struct in_addr na; + //na.s_addr = ~nm; + InetAddr nnm( ~srcmask ); + str << nnm.toString() << " "; + } } else { - str << srcaddr->toString() << " "; - - // cisco uses "wildcards" instead of netmasks - - //long nm = srcmask.to32BitInt(); - //struct in_addr na; - //na.s_addr = ~nm; - InetAddr nnm( ~srcmask ); - - str << nnm.toString() << " "; + str << "host " << srcaddr->toString() << " "; } } return str.str(); diff --git a/src/iosacl/iosacl.cpp b/src/iosacl/iosacl.cpp index fbc3a030c..78316efc6 100644 --- a/src/iosacl/iosacl.cpp +++ b/src/iosacl/iosacl.cpp @@ -56,7 +56,9 @@ #include "fwbuilder/FWObjectDatabase.h" #include "fwbuilder/Firewall.h" #include "fwbuilder/Interface.h" +#include "fwbuilder/Policy.h" #include "fwbuilder/IPv4.h" +#include "fwbuilder/IPv6.h" #include "fwbuilder/XMLTools.h" #include "fwbuilder/FWException.h" #include "fwbuilder/Tools.h" @@ -87,6 +89,8 @@ static int drp = -1; static int drn = -1; static int verbose = 0; static int test_mode = 0; +static bool ipv4_run = true; +static bool ipv6_run = true; FWObjectDatabase *objdb = NULL; @@ -124,10 +128,18 @@ int main(int argc, char * const * argv) int opt; - while( (opt=getopt(argc,argv,"x:vVf:d:r:tLo:")) != EOF ) + while( (opt=getopt(argc,argv,"x:vVf:d:r:tLo:46")) != EOF ) { switch(opt) { + case '4': + ipv4_run = true; + ipv6_run = false; + break; + case '6': + ipv4_run = false; + ipv6_run = true; + break; case 'd': wdir = strdup(optarg); break; @@ -318,36 +330,99 @@ int main(int argc, char * const * argv) if (user_name==NULL) throw FWException("Can't figure out your user name, aborting"); - Preprocessor* prep=new Preprocessor(objdb , fwobjectname, false); - prep->compile(); -/* - * Process firewall options, build OS network configuration script - */ + + OSConfigurator *oscnf=NULL; oscnf=new OSConfigurator_ios(objdb , fwobjectname, false); oscnf->prolog(); oscnf->processFirewallOptions(); -/* create compilers and run the whole thing */ - PolicyCompiler_iosacl *c = new PolicyCompiler_iosacl(objdb, - fwobjectname, - false, - oscnf); - if (test_mode) c->setTestMode(); - c->setDebugLevel( dl ); - c->setDebugRule( drp ); - c->setVerbose( verbose ); - if ( c->prolog() > 0 ) { - c->compile(); - c->epilog(); - } else - cout << " Nothing to compile in Policy \n" << flush; + list all_policies = fw->getByType(Policy::TYPENAME); + + int policy_rules_count = 0; + + vector ipv4_6_runs; + string generated_script; + + // 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. + // If neither is used, both parts will be done. + + if (options->getStr("ipv4_6_order").empty() || + options->getStr("ipv4_6_order") == "ipv4_first") + { + if (ipv4_run) ipv4_6_runs.push_back(false); + if (ipv6_run) ipv4_6_runs.push_back(true); + } + + if (options->getStr("ipv4_6_order") == "ipv6_first") + { + if (ipv6_run) ipv4_6_runs.push_back(true); + if (ipv4_run) ipv4_6_runs.push_back(false); + } + + for (vector::iterator i=ipv4_6_runs.begin(); + i!=ipv4_6_runs.end(); ++i) + { + bool ipv6_policy = *i; + + Preprocessor* prep = new Preprocessor(objdb , fwobjectname, false); + prep->compile(); + + for (list::iterator p=all_policies.begin(); + p!=all_policies.end(); ++p ) + { + Policy *policy = Policy::cast(*p); + + if (policy->isV6()!=ipv6_policy) continue; + + PolicyCompiler_iosacl c(objdb, fwobjectname, + ipv6_policy, oscnf); + + c.setSourceRuleSet( policy ); + + if (test_mode) c.setTestMode(); + c.setDebugLevel( dl ); + c.setDebugRule( drp ); + c.setVerbose( verbose ); + + if ( c.prolog() > 0 ) + { + c.compile(); + c.epilog(); + + if (c.haveErrorsAndWarnings()) + { + if (ipv6_policy) + { + generated_script += "\n\n"; + generated_script += "! ================ IPv6\n"; + generated_script += "\n\n"; + } else + { + generated_script += "\n\n"; + generated_script += "! ================ IPv4\n"; + generated_script += "\n\n"; + } + + generated_script += + "! Policy compiler errors and warnings:"; + generated_script += "\n"; + generated_script += c.getErrors("! "); + } + generated_script += c.getCompiledScript(); + + } else + cout << " Nothing to compile in Policy \n" << flush; + } + } #ifdef _WIN32 ofstream ofile(ofname.c_str(), ios::out|ios::binary); @@ -394,14 +469,8 @@ int main(int argc, char * const * argv) ofile << oscnf->getCompiledScript(); ofile << endl; - if (c->haveErrorsAndWarnings()) - { - ofile << "! Policy compiler errors and warnings:" - << endl; - ofile << c->getErrors("! "); - } + ofile << generated_script; - ofile << c->getCompiledScript(); ofile << endl; ofile << endl; diff --git a/src/ipt/ipt.cpp b/src/ipt/ipt.cpp index 351b23d90..8d5af80e0 100644 --- a/src/ipt/ipt.cpp +++ b/src/ipt/ipt.cpp @@ -577,14 +577,12 @@ _("Dynamic interface %s should not have an IP address object attached to it. Thi options->getStr("ipv4_6_order") == "ipv4_first") { if (ipv4_run) ipv4_6_runs.push_back(false); - if (ipv6_run && options->getBool("enable_ipv6")) - ipv4_6_runs.push_back(true); + if (ipv6_run) ipv4_6_runs.push_back(true); } if (options->getStr("ipv4_6_order") == "ipv6_first") { - if (ipv6_run && options->getBool("enable_ipv6")) - ipv4_6_runs.push_back(true); + if (ipv6_run) ipv4_6_runs.push_back(true); if (ipv4_run) ipv4_6_runs.push_back(false); } @@ -593,18 +591,6 @@ _("Dynamic interface %s should not have an IP address object attached to it. Thi { bool ipv6_policy = *i; - if (ipv6_policy) - { - generated_script += "\n\n"; - generated_script += "# ================ IPv6\n"; - generated_script += "\n\n"; - } else - { - generated_script += "\n\n"; - generated_script += "# ================ IPv4\n"; - generated_script += "\n\n"; - } - Preprocessor* prep = new Preprocessor( objdb , fwobjectname, ipv6_policy); prep->compile(); @@ -614,6 +600,7 @@ _("Dynamic interface %s should not have an IP address object attached to it. Thi ostringstream c_str; ostringstream m_str; ostringstream n_str; + bool empty_output = true; for (list::iterator p=all_nat.begin(); p!=all_nat.end(); ++p ) @@ -621,6 +608,8 @@ _("Dynamic interface %s should not have an IP address object attached to it. Thi NAT *nat = NAT::cast(*p); assignRuleSetChain(nat); string branch_name = nat->getName(); + + if (nat->isV6()!=ipv6_policy) continue; // compile NAT rules before policy rules because policy // compiler needs to know the number of virtual addresses @@ -661,6 +650,7 @@ _("Dynamic interface %s should not have an IP address object attached to it. Thi n_str << n.getCompiledScript(); n_str << n.commit(); n_str << endl; + empty_output = false; } } @@ -671,6 +661,8 @@ _("Dynamic interface %s should not have an IP address object attached to it. Thi assignRuleSetChain(policy); string branch_name = policy->getName(); + if (policy->isV6()!=ipv6_policy) continue; + MangleTableCompiler_ipt m( objdb , fwobjectname, ipv6_policy , oscnf ); @@ -713,6 +705,7 @@ _("Dynamic interface %s should not have an IP address object attached to it. Thi m_str << m.getCompiledScript(); m_str << m.commit(); m_str << endl; + empty_output = false; } } @@ -749,6 +742,7 @@ _("Dynamic interface %s should not have an IP address object attached to it. Thi c_str << c.getCompiledScript(); c_str << c.commit(); c_str << endl; + empty_output = false; } } @@ -758,10 +752,26 @@ _("Dynamic interface %s should not have an IP address object attached to it. Thi << "# ================ Table 'filter', automatic rules" << endl; reset_rules << c.flushAndSetDefaultPolicy(); + empty_output = false; } } + if (!empty_output) + { + if (ipv6_policy) + { + generated_script += "\n\n"; + generated_script += "# ================ IPv6\n"; + generated_script += "\n\n"; + } else + { + generated_script += "\n\n"; + generated_script += "# ================ IPv4\n"; + generated_script += "\n\n"; + } + } + generated_script += dumpScript(nocomm, fw, reset_rules.str(), n_str.str(), diff --git a/src/pf/pf.cpp b/src/pf/pf.cpp index 1fd2206c2..1d8635f12 100644 --- a/src/pf/pf.cpp +++ b/src/pf/pf.cpp @@ -684,14 +684,12 @@ int main(int argc, char * const *argv) options->getStr("ipv4_6_order") == "ipv4_first") { if (ipv4_run) ipv4_6_runs.push_back(false); - if (ipv6_run && options->getBool("enable_ipv6")) - ipv4_6_runs.push_back(true); + if (ipv6_run) ipv4_6_runs.push_back(true); } if (options->getStr("ipv4_6_order") == "ipv6_first") { - if (ipv6_run && options->getBool("enable_ipv6")) - ipv4_6_runs.push_back(true); + if (ipv6_run) ipv4_6_runs.push_back(true); if (ipv4_run) ipv4_6_runs.push_back(false); } @@ -712,6 +710,9 @@ int main(int argc, char * const *argv) p!=all_nat.end(); ++p ) { NAT *nat = NAT::cast(*p); + + if (nat->isV6()!=ipv6_policy) continue; + string ruleset_name = nat->getName(); if (Compiler::isRootRuleSet(nat)) ruleset_name = "__main__"; @@ -772,6 +773,9 @@ int main(int argc, char * const *argv) p!=all_policies.end(); ++p ) { Policy *policy = Policy::cast(*p); + + if (policy->isV6()!=ipv6_policy) continue; + string ruleset_name = policy->getName(); if (Compiler::isRootRuleSet(policy)) ruleset_name = "__main__";