mirror of
https://github.com/fwbuilder/fwbuilder
synced 2026-09-13 00:19:55 +02:00
444 lines
13 KiB
C++
444 lines
13 KiB
C++
/*
|
|
|
|
Firewall Builder
|
|
|
|
Copyright (C) 2007 NetCitadel, LLC
|
|
|
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
|
|
|
$Id: PolicyCompiler_iosacl_writers.cpp,v 1.1 2008/03/06 06:48:58 vkurland Exp $
|
|
|
|
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
|
|
|
|
*/
|
|
|
|
#include "PolicyCompiler_iosacl.h"
|
|
|
|
#include "fwbuilder/Firewall.h"
|
|
#include "fwbuilder/AddressRange.h"
|
|
#include "fwbuilder/RuleElement.h"
|
|
#include "fwbuilder/IPService.h"
|
|
#include "fwbuilder/ICMPService.h"
|
|
#include "fwbuilder/TCPService.h"
|
|
#include "fwbuilder/UDPService.h"
|
|
#include "fwbuilder/CustomService.h"
|
|
#include "fwbuilder/Policy.h"
|
|
#include "fwbuilder/FWOptions.h"
|
|
#include "fwbuilder/FWObjectDatabase.h"
|
|
#include "fwbuilder/Interface.h"
|
|
#include "fwbuilder/IPv4.h"
|
|
#include "fwbuilder/Network.h"
|
|
#include "fwbuilder/Management.h"
|
|
#include "fwbuilder/Resources.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 <fstream>
|
|
#include <sstream>
|
|
#include <algorithm>
|
|
#include <functional>
|
|
|
|
#include <assert.h>
|
|
|
|
using namespace libfwbuilder;
|
|
using namespace fwcompiler;
|
|
using namespace std;
|
|
|
|
|
|
bool PolicyCompiler_iosacl::ClearACLs::processNext()
|
|
{
|
|
PolicyCompiler_iosacl *iosacl_comp=dynamic_cast<PolicyCompiler_iosacl*>(compiler);
|
|
string vers = compiler->fw->getStr("version");
|
|
string platform = compiler->fw->getStr("platform");
|
|
string clearACLcmd = Resources::platform_res[platform]->getResourceStr(
|
|
string("/FWBuilderResources/Target/options/")+
|
|
"version_"+vers+"/iosacl_commands/clear_acl");
|
|
|
|
|
|
slurp();
|
|
if (tmp_queue.size()==0) return false;
|
|
|
|
if ( compiler->fw->getOptionsObject()->getBool("iosacl_acl_basic") )
|
|
{
|
|
compiler->output << clearACLcmd << endl;
|
|
}
|
|
|
|
if (compiler->fw->getOptionsObject()->getBool("iosacl_acl_substitution"))
|
|
{
|
|
for (map<string,ciscoACL*>::iterator i=iosacl_comp->acls.begin();
|
|
i!=iosacl_comp->acls.end(); ++i)
|
|
{
|
|
ciscoACL *acl=(*i).second;
|
|
compiler->output << clearACLcmd << " " << acl->workName() << endl;
|
|
}
|
|
compiler->output << endl;
|
|
}
|
|
|
|
if ( !compiler->fw->getOptionsObject()->getBool("iosacl_acl_no_clear") )
|
|
{
|
|
string clearICMPcmd = Resources::platform_res[platform]->getResourceStr(
|
|
string("/FWBuilderResources/Target/options/")+
|
|
"version_"+vers+"/iosacl_commands/clear_icmp");
|
|
string clearTelnetcmd = Resources::platform_res[platform]->getResourceStr(
|
|
string("/FWBuilderResources/Target/options/")+
|
|
"version_"+vers+"/iosacl_commands/clear_telnet");
|
|
string clearSSHcmd = Resources::platform_res[platform]->getResourceStr(
|
|
string("/FWBuilderResources/Target/options/")+
|
|
"version_"+vers+"/iosacl_commands/clear_ssh");
|
|
//compiler->output << clearICMPcmd << endl;
|
|
//compiler->output << clearTelnetcmd << endl;
|
|
//compiler->output << clearSSHcmd << endl;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void PolicyCompiler_iosacl::PrintCompleteACLs::printRulesForACL::operator()(
|
|
Rule* rule)
|
|
{
|
|
// print rule if it belongs to ACL <acl>
|
|
|
|
PolicyRule *prule = PolicyRule::cast(rule);
|
|
|
|
string acl_name = prule->getStr("acl");
|
|
assert (acl_name!="");
|
|
|
|
ciscoACL *rule_acl = iosacl_comp->acls[acl_name];
|
|
assert(rule_acl!=NULL);
|
|
|
|
if (acl == rule_acl)
|
|
{
|
|
*output << print_acl_p->_printRule(prule);
|
|
}
|
|
}
|
|
|
|
bool PolicyCompiler_iosacl::PrintCompleteACLs::processNext()
|
|
{
|
|
PolicyCompiler_iosacl *iosacl_comp=dynamic_cast<PolicyCompiler_iosacl*>(compiler);
|
|
string vers = compiler->fw->getStr("version");
|
|
string platform = compiler->fw->getStr("platform");
|
|
string clearACLCmd = Resources::platform_res[platform]->getResourceStr(
|
|
string("/FWBuilderResources/Target/options/")+
|
|
"version_"+vers+"/iosacl_commands/clear_ip_acl");
|
|
|
|
assert( !clearACLCmd.empty());
|
|
|
|
slurp();
|
|
if (tmp_queue.size()==0) return false;
|
|
|
|
if ( compiler->fw->getOptionsObject()->getBool("iosacl_acl_basic") ||
|
|
compiler->fw->getOptionsObject()->getBool("iosacl_acl_substitution"))
|
|
{
|
|
for (map<string,ciscoACL*>::iterator i=iosacl_comp->acls.begin();
|
|
i!=iosacl_comp->acls.end(); ++i)
|
|
{
|
|
ciscoACL *acl=(*i).second;
|
|
compiler->output << clearACLCmd << " " << acl->workName() << endl;
|
|
}
|
|
compiler->output << endl;
|
|
}
|
|
|
|
for (map<string,ciscoACL*>::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;
|
|
std::for_each(tmp_queue.begin(), tmp_queue.end(),
|
|
printRulesForACL(iosacl_comp, this, acl, &(compiler->output)));
|
|
compiler->output << "exit" << endl;
|
|
compiler->output << endl;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
string PolicyCompiler_iosacl::PrintRule::_printRule(PolicyRule *rule)
|
|
{
|
|
PolicyCompiler_iosacl *iosacl_comp =
|
|
dynamic_cast<PolicyCompiler_iosacl*>(compiler);
|
|
FWOptions *ruleopt =rule->getOptionsObject();
|
|
bool write_comments =
|
|
compiler->fw->getOptionsObject()->getBool("iosacl_include_comments");
|
|
|
|
ostringstream ruleout;
|
|
ostringstream aclstr;
|
|
|
|
string rl=rule->getLabel();
|
|
|
|
if (write_comments)
|
|
{
|
|
if (rl!=current_rule_label1)
|
|
{
|
|
ruleout << "! " << endl;
|
|
ruleout << "! Rule " << rl << endl;
|
|
|
|
string comm=rule->getComment();
|
|
string::size_type c1,c2;
|
|
c1=0;
|
|
while ( (c2=comm.find('\n',c1))!=string::npos ) {
|
|
ruleout << "! " << comm.substr(c1,c2-c1) << endl;
|
|
c1=c2+1;
|
|
}
|
|
ruleout << "! " << comm.substr(c1) << endl;
|
|
ruleout << "! " << endl;
|
|
|
|
current_rule_label1=rl;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* all three rule elements contain exactly one object, which can
|
|
* be either group (in case processor CreateObjectGroups created
|
|
* object group for it) or a regular object
|
|
*/
|
|
RuleElementSrc *src=rule->getSrc();
|
|
RuleElementDst *dst=rule->getDst();
|
|
RuleElementSrv *srv=rule->getSrv();
|
|
|
|
assert(src->size()==1);
|
|
assert(dst->size()==1);
|
|
assert(srv->size()==1);
|
|
|
|
FWObject *srcobj=src->front();
|
|
FWObject *dstobj=dst->front();
|
|
FWObject *srvobj=srv->front();
|
|
|
|
assert(srcobj);
|
|
assert(dstobj);
|
|
assert(srvobj);
|
|
|
|
if (FWReference::cast(srcobj)!=NULL)
|
|
{
|
|
srcobj=FWReference::cast(srcobj)->getPointer();
|
|
assert(srcobj);
|
|
}
|
|
if (FWReference::cast(dstobj)!=NULL)
|
|
{
|
|
dstobj=FWReference::cast(dstobj)->getPointer();
|
|
assert(dstobj);
|
|
}
|
|
if (FWReference::cast(srvobj)!=NULL)
|
|
{
|
|
srvobj=FWReference::cast(srvobj)->getPointer();
|
|
assert(srvobj);
|
|
}
|
|
|
|
string acl_name=rule->getStr("acl");
|
|
assert (acl_name!="");
|
|
|
|
ciscoACL *acl = iosacl_comp->acls[acl_name];
|
|
assert(acl!=NULL);
|
|
|
|
/*
|
|
* Assemble ACL command in aclstr
|
|
*/
|
|
|
|
aclstr << _printAction(rule);
|
|
|
|
aclstr << Service::cast(srvobj)->getProtocolName();
|
|
aclstr << " ";
|
|
aclstr << _printAddr( compiler->getFirstSrc(rule) );
|
|
aclstr << _printSrcService( compiler->getFirstSrv(rule) );
|
|
aclstr << _printAddr( compiler->getFirstDst(rule) );
|
|
aclstr << _printDstService( compiler->getFirstSrv(rule) );
|
|
aclstr << _printLog( rule );
|
|
// "fragments" should be the last option in the access-list command
|
|
aclstr << _printFragm( compiler->getFirstSrv(rule) );
|
|
|
|
// aclstr << endl;
|
|
|
|
ruleout << acl->addLine(aclstr.str());
|
|
|
|
return ruleout.str();
|
|
}
|
|
|
|
string PolicyCompiler_iosacl::PrintRule::_printAction(PolicyRule *rule)
|
|
{
|
|
ostringstream str;
|
|
|
|
switch (rule->getAction()) {
|
|
case PolicyRule::Accept: str << "permit "; break;
|
|
case PolicyRule::Deny: str << "deny "; break;
|
|
case PolicyRule::Reject: str << "deny "; break;
|
|
default: str << rule->getActionAsString() << " ";
|
|
}
|
|
return str.str();
|
|
}
|
|
|
|
string PolicyCompiler_iosacl::PrintRule::_printACL(PolicyRule *rule)
|
|
{
|
|
// PolicyCompiler_iosacl *iosacl_comp=dynamic_cast<PolicyCompiler_iosacl*>(compiler);
|
|
|
|
string acl_name=rule->getStr("acl");
|
|
assert (acl_name!="");
|
|
|
|
return acl_name+" ";
|
|
}
|
|
|
|
string PolicyCompiler_iosacl::PrintRule::_printLog(PolicyRule *rule)
|
|
{
|
|
if (rule->getLogging())
|
|
{
|
|
FWOptions *ruleopt =rule->getOptionsObject();
|
|
if (ruleopt->getBool("iosacl_log_input")) return "log-input ";
|
|
return "log ";
|
|
}
|
|
return "";
|
|
}
|
|
|
|
string PolicyCompiler_iosacl::PrintRule::_printSrcService(libfwbuilder::Service *srv)
|
|
{
|
|
ostringstream str;
|
|
|
|
if (TCPService::isA(srv) || UDPService::isA(srv))
|
|
{
|
|
int rs=TCPUDPService::cast(srv)->getSrcRangeStart();
|
|
int re=TCPUDPService::cast(srv)->getSrcRangeEnd();
|
|
|
|
if (rs<0) rs=0;
|
|
if (re<0) re=0;
|
|
|
|
if (rs>0 || re>0) {
|
|
if (rs==re) str << "eq " << rs << " ";
|
|
else
|
|
if (rs==0 && re!=0) str << "lt " << re << " ";
|
|
else
|
|
if (rs!=0 && re==65535) str << "gt " << rs << " ";
|
|
else
|
|
str << "range " << rs << " " << re << " ";
|
|
}
|
|
}
|
|
return str.str();
|
|
}
|
|
|
|
string PolicyCompiler_iosacl::PrintRule::_printFragm(Service *srv)
|
|
{
|
|
if (IPService::isA(srv) && (srv->getBool("fragm") || srv->getBool("short_fragm")))
|
|
return "fragments ";
|
|
|
|
return "";
|
|
}
|
|
|
|
string PolicyCompiler_iosacl::PrintRule::_printDstService(Service *srv)
|
|
{
|
|
ostringstream str;
|
|
|
|
if (TCPService::isA(srv) || UDPService::isA(srv))
|
|
{
|
|
int rs=TCPUDPService::cast(srv)->getDstRangeStart();
|
|
int re=TCPUDPService::cast(srv)->getDstRangeEnd();
|
|
|
|
if (rs<0) rs=0;
|
|
if (re<0) re=0;
|
|
|
|
if (rs>0 || re>0) {
|
|
if (rs==re) str << "eq " << rs << " ";
|
|
else
|
|
if (rs==0 && re!=0) str << "lt " << re << " ";
|
|
else
|
|
if (rs!=0 && re==65535) str << "gt " << rs << " ";
|
|
else
|
|
str << "range " << rs << " " << re << " ";
|
|
}
|
|
}
|
|
if (TCPService::isA(srv) && srv->getBool("established"))
|
|
str << "established ";
|
|
|
|
if (ICMPService::isA(srv) && srv->getInt("type")!=-1)
|
|
str << srv->getStr("type") << " ";
|
|
return str.str();
|
|
}
|
|
|
|
string PolicyCompiler_iosacl::PrintRule::_printAddr(libfwbuilder::Address *o)
|
|
{
|
|
if (Interface::cast(o)!=NULL)
|
|
{
|
|
Interface *interface_=Interface::cast(o);
|
|
if (interface_->isDyn())
|
|
{
|
|
return string("interface ") + interface_->getLabel() + " ";
|
|
}
|
|
}
|
|
|
|
ostringstream str;
|
|
|
|
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());
|
|
|
|
if (srcaddr->isAny() && srcmask.isAny())
|
|
{
|
|
str << "any ";
|
|
} else {
|
|
if (srcmask.isHostMask())
|
|
{
|
|
str << "host " << srcaddr->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() << " ";
|
|
}
|
|
}
|
|
return str.str();
|
|
} else
|
|
{
|
|
compiler->abort(string("Object ") + o->getName() +
|
|
string(" (id=") + o->getId() + string(") ") +
|
|
string(" has no ip address and can not be used ") +
|
|
string("in the rule."));
|
|
}
|
|
}
|
|
|
|
/*
|
|
* the following additional attributes should have been defined by now:
|
|
*
|
|
* "acl" - string, name of the access list
|
|
* choices are: outside-in, outside-out, inside-in, indside-out,
|
|
* dmz-in, dmz-out etc.
|
|
* General rule for the acl name: "iface_name-{in,out}"
|
|
*/
|
|
bool PolicyCompiler_iosacl::PrintRule::processNext()
|
|
{
|
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
|
|
|
tmp_queue.push_back(rule);
|
|
|
|
compiler->output << _printRule(rule);
|
|
|
|
return true;
|
|
}
|
|
|