1
0
mirror of https://github.com/fwbuilder/fwbuilder synced 2026-03-23 03:37:15 +01:00
fwbuilder/src/cisco_lib/PolicyCompiler_pix_v6_acls.cpp

369 lines
12 KiB
C++

/*
Firewall Builder
Copyright (C) 2002 NetCitadel, LLC
Author: Vadim Kurland vadim@vk.crocodile.org
$Id$
This program is free software which we release under the GNU General Public
License. You may redistribute and/or modify this program under the terms
of that license as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
To get a copy of the GNU General Public License, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Rule processors in this module build ACLs for PIX v6
they employ number of assumptions that are only valid for PIX <7.0
*/
#include "config.h"
#include "PolicyCompiler_pix.h"
#include "NATCompiler_pix.h"
#include "PIXObjectGroup.h"
#include "fwbuilder/FWObjectDatabase.h"
#include "fwbuilder/RuleElement.h"
#include "fwbuilder/IPService.h"
#include "fwbuilder/ICMPService.h"
#include "fwbuilder/TCPService.h"
#include "fwbuilder/UDPService.h"
#include "fwbuilder/Network.h"
#include "fwbuilder/Policy.h"
#include "fwbuilder/Interface.h"
#include "fwbuilder/Management.h"
#include "fwbuilder/Resources.h"
#include "fwbuilder/AddressTable.h"
#include <iostream>
#if __GNUC__ > 3 || \
(__GNUC__ == 3 && (__GNUC_MINOR__ > 2 || (__GNUC_MINOR__ == 2 ) ) ) || \
_MSC_VER
# include <streambuf>
#else
# include <streambuf.h>
#endif
#include <iomanip>
#include <algorithm>
#include <functional>
#include <assert.h>
using namespace libfwbuilder;
using namespace fwcompiler;
using namespace std;
bool PolicyCompiler_pix::InterfaceAndDirection_v6::processNext()
{
PolicyRule *rule=getNext(); if (rule==NULL) return false;
tmp_queue.push_back(rule);
bool icmp_cmd = rule->getBool("icmp_cmd");
bool ssh_telnet_cmd = rule->getBool("ssh_telnet_cmd");
int interface_id = rule->getInterfaceId();
if (rule->getDirection()==PolicyRule::Undefined)
rule->setDirection( PolicyRule::Both );
if (interface_id==-1 && rule->getDirection()==PolicyRule::Both)
return true;
if (interface_id==-1 && !icmp_cmd && !ssh_telnet_cmd && (
rule->getDirection()==PolicyRule::Inbound ||
rule->getDirection()==PolicyRule::Outbound)
) compiler->abort(rule, "Direction set without interface");
return true;
}
/*
* rules with direction 'both' associated with an interface are split
* and copies are assigned directions Inbound and Outbound
*
* rules with direction 'both' not associated with any interface are
* simply converted to "Inbound". This is because we only generate
* outbound ACLs for rules that explicitly were defined by the user
* with direction "Outbound"; everything else is implemented using
* inbound ACLs
*
* 04/21/06 --vk
*/
bool PolicyCompiler_pix::SplitDirection_v6::processNext()
{
PolicyRule *rule=getNext(); if (rule==NULL) return false;
FWObject *rule_iface = compiler->dbcopy->findInIndex(rule->getInterfaceId());
if (rule->getDirection()==PolicyRule::Both)
{
if (rule_iface!=NULL)
{
PolicyRule *r= compiler->dbcopy->createPolicyRule();
compiler->temp_ruleset->add(r);
r->duplicate(rule);
r->setDirection(PolicyRule::Inbound);
tmp_queue.push_back(r);
r= compiler->dbcopy->createPolicyRule();
compiler->temp_ruleset->add(r);
r->duplicate(rule);
r->setDirection(PolicyRule::Outbound);
tmp_queue.push_back(r);
} else
{
rule->setDirection(PolicyRule::Inbound);
tmp_queue.push_back(rule);
}
} else
tmp_queue.push_back(rule);
return true;
}
/**
* this processor emulates outbound ACL by splitting a rule onto
* several rules and assigning them to interfaces. This processor
* works only with rules that have direction "Outbound" and have
* interface specified.
*
* Prerequisities:
*
* Rule should have been split before this processor is called if
* objects in src and/or dst belong to different network zones
*
*
* Internet ("any")
* ^
* |
* | i4
* +----------+
* i1| |i3
* ---------------+ PIX +----------------
* host1 | | host3
* +----------+
* |i2
* |
* |host2
*
* src dst interface
*
* h1 h2 i2 change interface to i1
* any h2 i2 split, use all interfaces but i2
* h1 any i2 change interface to i1
* any any i2 split, use all interfaces but i2
*
*
* FWSM v2.3 and beyond, as well as PIX 7.0, support outbound ACLs
* (via "access-group out ..." command) We do not need to do this
* for these platforms.
*/
bool PolicyCompiler_pix::EmulateOutboundACL_v6::processNext()
{
Helper helper(compiler);
PolicyRule *rule=getNext(); if (rule==NULL) return false;
FWObject *rule_iface = compiler->dbcopy->findInIndex(rule->getInterfaceId());
if (rule->getDirection()==PolicyRule::Outbound && rule_iface!=NULL)
{
if ( compiler->fw->getOptionsObject()->getBool("pix_emulate_out_acl") )
{
RuleElementSrc *src=rule->getSrc(); assert(src);
RuleElementDst *dst=rule->getDst(); assert(dst);
try
{
if (!src->isAny())
{
int iface1_id = helper.findInterfaceByNetzone(
compiler->getFirstSrc(rule) );
/* special case: interface detected via comparison of src and the
* network zone is the same as the one this rule is assigned to, but
* direction is Outbound - drop this rule
*/
if (iface1_id==rule->getInterfaceId())
{
return true;
}
rule->setInterfaceId(iface1_id);
rule->setDirection(PolicyRule::Inbound);
tmp_queue.push_back(rule);
} else
{
int iface2_id;
iface2_id = helper.findInterfaceByNetzone(
compiler->getFirstDst(rule) );
list<FWObject*> l2=compiler->fw->getByType(Interface::TYPENAME);
for (list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i)
{
if ( (*i)->getId()==iface2_id ) continue;
PolicyRule *r= compiler->dbcopy->createPolicyRule();
compiler->temp_ruleset->add(r);
r->duplicate(rule);
r->setInterfaceId((*i)->getId());
rule->setDirection(PolicyRule::Inbound);
tmp_queue.push_back(r);
}
}
} catch (string addr)
{
ostringstream str;
str << "Can not find interface to assign rule "
<< rule->getLabel()
<< ": " << endl
<< "Address " << addr
<< " does not match address or network zone of any interface"
<< endl;
compiler->abort(rule, str.str());
}
} else
compiler->abort(
rule,
"Outbound ACLs are not supported and emulation is "
"not activated");
} else
tmp_queue.push_back(rule);
return true;
}
/**
* this processor assigns rules to interfaces (since PIX only
* supports ACLs on interfaces and direction can only be "inbound").
*
*
* Internet ("any")
* ^
* |
* | i4
* +----------+
* i1| |i3
* ---------------+ PIX +----------------
* host1 | | host3
* +----------+
* |i2
* |
* |host2
*
* src dst assign to interface
*
* any i1 i1
* any i2 i2
* any i3 i3
* any i4 i4
* any host2 all
* host1 host2 i1
* host1 any i1
* any any all
*/
bool PolicyCompiler_pix::assignRuleToInterface_v6::processNext()
{
PolicyRule *rule=getNext(); if (rule==NULL) return false;
Helper helper(compiler);
RuleElementSrc *src=rule->getSrc(); assert(src);
RuleElementDst *dst=rule->getDst(); assert(dst);
if (rule->getInterfaceId()==-1)
{
try
{
if (! src->isAny() )
{
Address *a=compiler->getFirstSrc(rule);
int iface1_id = helper.findInterfaceByNetzone(a);
rule->setInterfaceId(iface1_id);
tmp_queue.push_back(rule);
} else
{
Address *a=compiler->getFirstDst(rule);
if ( ! dst->isAny() && compiler->complexMatch(a,compiler->fw))
{
int iface2_id = helper.findInterfaceByNetzone( a );
rule->setInterfaceId(iface2_id);
rule->setStr("direction","Inbound");
tmp_queue.push_back(rule);
return true;
}
list<FWObject*> l2 = compiler->fw->getByTypeDeep(Interface::TYPENAME);
for (list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i)
{
Interface *intf = Interface::cast(*i);
if (intf->isUnprotected()) continue;
PolicyRule *r = compiler->dbcopy->createPolicyRule();
compiler->temp_ruleset->add(r);
r->duplicate(rule);
r->setInterfaceId(intf->getId());
r->setStr("direction","Inbound");
tmp_queue.push_back(r);
}
}
} catch (string addr)
{
ostringstream str;
str << "Can not find interface to assign rule "
<< rule->getLabel()
<< ": " << endl
<< "Address " << addr
<< " does not match address or network zone of any interface"
<< endl;
compiler->abort(rule, str.str());
}
} else {
tmp_queue.push_back(rule);
}
return true;
}
/*
* This processor is called after emulateOutboundACL
*/
bool PolicyCompiler_pix::pickACL_v6::processNext()
{
PolicyCompiler_pix *pix_comp=dynamic_cast<PolicyCompiler_pix*>(compiler);
PolicyRule *rule=getNext(); if (rule==NULL) return false;
Interface *rule_iface = Interface::cast(compiler->dbcopy->findInIndex(rule->getInterfaceId()));
if(rule_iface==NULL)
{
compiler->abort(
rule, "Missing interface assignment");
}
string acl_name= rule_iface->getLabel() + "_acl_in";
rule->setStr("acl",acl_name);
ciscoACL *acl = new ciscoACL(acl_name, rule_iface, "in");
pix_comp->acls[acl_name] = acl;
acl->setWorkName(acl_name);
tmp_queue.push_back(rule);
return true;
}