mirror of
https://github.com/fwbuilder/fwbuilder
synced 2026-09-11 15:41:41 +02:00
merging cisco and pix modules
This commit is contained in:
@@ -25,6 +25,9 @@ for d in src/ \
|
|||||||
src/pf/ \
|
src/pf/ \
|
||||||
src/ipf/ \
|
src/ipf/ \
|
||||||
src/ipfw/ \
|
src/ipfw/ \
|
||||||
|
src/cisco_lib \
|
||||||
|
src/iosacl \
|
||||||
|
src/pix \
|
||||||
src/parsers/
|
src/parsers/
|
||||||
do
|
do
|
||||||
(cd $d; ${QMAKE} $C)
|
(cd $d; ${QMAKE} $C)
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2004 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: ACL.cpp,v 1.1 2008/03/06 06:48:55 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 "ACL.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
string ciscoACL::addLine(const std::string &s)
|
||||||
|
{
|
||||||
|
acl.push_back(s);
|
||||||
|
nlines++;
|
||||||
|
return printLastLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adds remark to access list. Checks and adds each remark only
|
||||||
|
* once. We use rule labels for remarks
|
||||||
|
*/
|
||||||
|
string ciscoACL::addRemark(const std::string &rl)
|
||||||
|
{
|
||||||
|
if (_last_rule_label!=rl)
|
||||||
|
{
|
||||||
|
acl.push_back(" remark "+rl);
|
||||||
|
_last_rule_label=rl;
|
||||||
|
nlines++;
|
||||||
|
return printLastLine();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string ciscoACL::print()
|
||||||
|
{
|
||||||
|
ostringstream str;
|
||||||
|
|
||||||
|
for (list<string>::iterator s=acl.begin(); s!=acl.end(); s++)
|
||||||
|
str << printLine(*s);
|
||||||
|
|
||||||
|
return str.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
string ciscoACL::printLastLine()
|
||||||
|
{
|
||||||
|
return printLine(acl.back());
|
||||||
|
}
|
||||||
|
|
||||||
|
string ciscoACL::printLine(const string &s)
|
||||||
|
{
|
||||||
|
ostringstream str;
|
||||||
|
|
||||||
|
// _ip_acl means Cisco IOS "ip access-list extended <name>" style ACL
|
||||||
|
// actual lines of the access list just start with "permit" or "deny"
|
||||||
|
if ( s.find('!')!=0 )
|
||||||
|
{
|
||||||
|
if (_ip_acl) str << " ";
|
||||||
|
else str << "access-list " << _workName << " ";
|
||||||
|
}
|
||||||
|
str << s << endl;
|
||||||
|
|
||||||
|
return str.str();
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2004 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: ACL.h,v 1.1 2008/03/06 06:48:55 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
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ACL_H
|
||||||
|
#define __ACL_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include "fwbuilder/Interface.h"
|
||||||
|
|
||||||
|
class ciscoACL {
|
||||||
|
|
||||||
|
bool _ip_acl;
|
||||||
|
std::string _name;
|
||||||
|
std::string _workName;
|
||||||
|
libfwbuilder::Interface *_interface;
|
||||||
|
std::string _dir;
|
||||||
|
std::string _last_rule_label;
|
||||||
|
int nlines;
|
||||||
|
std::list<std::string> acl;
|
||||||
|
|
||||||
|
std::string printLine(const std::string &s);
|
||||||
|
|
||||||
|
public:
|
||||||
|
ciscoACL() {
|
||||||
|
_ip_acl = false;
|
||||||
|
_name = "";
|
||||||
|
_workName = "";
|
||||||
|
_interface = NULL;
|
||||||
|
_dir = "in";
|
||||||
|
nlines = 0;
|
||||||
|
_last_rule_label = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
ciscoACL(const std::string &n,
|
||||||
|
libfwbuilder::Interface *intf,
|
||||||
|
const std::string &d="in",
|
||||||
|
bool _ip_list=false)
|
||||||
|
{
|
||||||
|
_ip_acl = _ip_list;
|
||||||
|
_name = n;
|
||||||
|
_workName = "";
|
||||||
|
_interface = intf;
|
||||||
|
_dir = d;
|
||||||
|
nlines = 0;
|
||||||
|
_last_rule_label = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string addLine(const std::string &s);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adds remark to access list. Checks and adds each remark only
|
||||||
|
* once. We use rule labels for remarks
|
||||||
|
*/
|
||||||
|
std::string addRemark(const std::string &rl);
|
||||||
|
|
||||||
|
void setName(const std::string &s) { _name=s; }
|
||||||
|
std::string name() { return _name; }
|
||||||
|
|
||||||
|
void setWorkName(const std::string &s) { _workName=s; }
|
||||||
|
std::string workName() { return _workName; }
|
||||||
|
|
||||||
|
void setInterface(libfwbuilder::Interface *intf) { _interface=intf; }
|
||||||
|
libfwbuilder::Interface* getInterface() { return _interface; }
|
||||||
|
|
||||||
|
void setDirection(const std::string &d) { _dir=d; }
|
||||||
|
std::string direction() { return _dir; }
|
||||||
|
|
||||||
|
|
||||||
|
std::string print();
|
||||||
|
std::string printLastLine();
|
||||||
|
|
||||||
|
int size() { return nlines; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,255 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2002 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: Helper.cpp,v 1.1 2008/03/06 06:48:56 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 "Helper.h"
|
||||||
|
|
||||||
|
#include <fwbuilder/Interface.h>
|
||||||
|
#include <fwbuilder/ObjectGroup.h>
|
||||||
|
#include <fwbuilder/IPAddress.h>
|
||||||
|
#include <fwbuilder/FWObjectDatabase.h>
|
||||||
|
#include <fwbuilder/RuleElement.h>
|
||||||
|
#include <fwbuilder/Rule.h>
|
||||||
|
#include "fwbuilder/Resources.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
using namespace libfwbuilder;
|
||||||
|
using namespace fwcompiler;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
bool Helper::belongsTo(Address *obj, const IPAddress &a)
|
||||||
|
{
|
||||||
|
const IPNetwork n1( obj->getAddress() ,
|
||||||
|
(Interface::cast(obj))?Netmask("255.255.255.255"):obj->getNetmask() );
|
||||||
|
|
||||||
|
return n1.belongs(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Helper::belongsTo(Address *obj, Address *addr)
|
||||||
|
{
|
||||||
|
return belongsTo(obj,addr->getAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned long calculateDimension(FWObject* obj)
|
||||||
|
{
|
||||||
|
if (Group::cast(obj)!=NULL) {
|
||||||
|
unsigned long res=0;
|
||||||
|
for (FWObject::iterator i1=obj->begin(); i1!=obj->end(); ++i1)
|
||||||
|
{
|
||||||
|
unsigned long n=calculateDimension( *i1 );
|
||||||
|
if (n==LONG_MAX) return n;
|
||||||
|
if (LONG_MAX-res<n) return LONG_MAX; // prevent overflow
|
||||||
|
res+=n;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
Address *a=Address::cast(obj);
|
||||||
|
if (a!=NULL)
|
||||||
|
{
|
||||||
|
if (a->isAny()) return LONG_MAX;
|
||||||
|
return a->dimension();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Helper::expand_group_recursive_no_cache(FWObject *o,list<FWObject*> &ol)
|
||||||
|
{
|
||||||
|
if (Group::cast( o )!=NULL) {
|
||||||
|
for (FWObject::iterator i2=o->begin(); i2!=o->end(); ++i2)
|
||||||
|
{
|
||||||
|
FWObject *o1= *i2;
|
||||||
|
if (FWReference::cast(o1)!=NULL) o1=FWReference::cast(o1)->getPointer();
|
||||||
|
assert(o1);
|
||||||
|
|
||||||
|
expand_group_recursive_no_cache(o1,ol);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ol.push_back( o );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Helper::expand_group_recursive(FWObject *o,list<FWObject*> &ol)
|
||||||
|
{
|
||||||
|
if (Group::cast( o )!=NULL) {
|
||||||
|
for (FWObject::iterator i2=o->begin(); i2!=o->end(); ++i2)
|
||||||
|
{
|
||||||
|
FWObject *o1= *i2;
|
||||||
|
if (FWReference::cast(o1)!=NULL) o1=FWReference::cast(o1)->getPointer();
|
||||||
|
assert(o1);
|
||||||
|
|
||||||
|
expand_group_recursive(o1,ol);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ol.push_back( o );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string Helper::findInterfaceByAddress(libfwbuilder::Address *obj)
|
||||||
|
{
|
||||||
|
return findInterfaceByAddress(obj->getAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
string Helper::findInterfaceByAddress(const libfwbuilder::IPAddress &addr)
|
||||||
|
{
|
||||||
|
Firewall *fw=compiler->fw;
|
||||||
|
list<FWObject*> l2=fw->getByType(Interface::TYPENAME);
|
||||||
|
for (list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i) {
|
||||||
|
Interface *iface=Interface::cast(*i);
|
||||||
|
IPNetwork n( iface->getAddress() , iface->getNetmask() );
|
||||||
|
if ( n.belongs( addr ) ) return iface->getId();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
string Helper::findInterfaceByNetzone(Address *obj)
|
||||||
|
{
|
||||||
|
return findInterfaceByNetzone(obj->getAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
string Helper::findInterfaceByNetzone(const IPAddress &addr) throw(string)
|
||||||
|
{
|
||||||
|
Firewall *fw=compiler->fw;
|
||||||
|
map<string,FWObject*> zones;
|
||||||
|
FWObjectTypedChildIterator i=fw->findByType(Interface::TYPENAME);
|
||||||
|
for ( ; i!=i.end(); ++i)
|
||||||
|
{
|
||||||
|
string netzone_id = (*i)->getStr("network_zone");
|
||||||
|
if (netzone_id != "")
|
||||||
|
{
|
||||||
|
FWObject *netzone=fw->getRoot()->findInIndex(netzone_id);
|
||||||
|
for (list<FWObject*>::iterator j=netzone->begin();
|
||||||
|
j!=netzone->end(); ++j)
|
||||||
|
{
|
||||||
|
assert(Address::cast(*j)!=NULL);
|
||||||
|
if ( belongsTo( Address::cast(*j) , addr ) )
|
||||||
|
zones[(*i)->getId()]=netzone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* now compare dimensions of all netzones that contain address obj and
|
||||||
|
* pick the one with smallest dimension
|
||||||
|
*/
|
||||||
|
string res_id;
|
||||||
|
unsigned long res_dim=LONG_MAX;
|
||||||
|
for (map<string,FWObject*>::iterator i=zones.begin(); i!=zones.end(); ++i)
|
||||||
|
{
|
||||||
|
string iface_id=(*i).first;
|
||||||
|
FWObject *netzone=(*i).second;
|
||||||
|
unsigned long dim=calculateDimension(netzone);
|
||||||
|
|
||||||
|
if (dim<=res_dim)
|
||||||
|
{
|
||||||
|
res_id=iface_id;
|
||||||
|
res_dim=dim;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Subnets defined by addresses of interfaces are automatically part
|
||||||
|
* of the corresponding network zones
|
||||||
|
*/
|
||||||
|
if (res_id.empty())
|
||||||
|
res_id=findInterfaceByAddress( addr );
|
||||||
|
|
||||||
|
if (res_id.empty())
|
||||||
|
throw( string("Can not find interface with network zone that includes address ") + addr.toString());
|
||||||
|
return res_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
list<string> Helper::getAllInterfaceIDs()
|
||||||
|
{
|
||||||
|
Firewall *fw=compiler->fw;
|
||||||
|
list<string> intf_id_list;
|
||||||
|
FWObjectTypedChildIterator i=fw->findByType(Interface::TYPENAME);
|
||||||
|
for ( ; i!=i.end(); ++i)
|
||||||
|
{
|
||||||
|
Interface *ifs = Interface::cast(*i);
|
||||||
|
assert(ifs);
|
||||||
|
if (ifs->isUnprotected()) continue; // skip!
|
||||||
|
intf_id_list.push_back( (*i)->getId() );
|
||||||
|
}
|
||||||
|
return intf_id_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
list<string> Helper::findInterfaceByNetzoneOrAll(RuleElement *re)
|
||||||
|
{
|
||||||
|
Firewall *fw=compiler->fw;
|
||||||
|
list<string> intf_id_list;
|
||||||
|
if (re->isAny())
|
||||||
|
{
|
||||||
|
return getAllInterfaceIDs();
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
FWObject *fo = re->front();
|
||||||
|
if (FWReference::cast(fo)!=NULL) fo=FWReference::cast(fo)->getPointer();
|
||||||
|
Address *a = Address::cast(fo);
|
||||||
|
if (a==NULL)
|
||||||
|
{
|
||||||
|
Rule *rule = Rule::cast(re->getParent());
|
||||||
|
compiler->abort(string("findInterfaceByNetzoneOrAll failed to retrieve first object from the rule element; is argument not of the type RuleElementSrc or RuleElementDst ? Rule ") + rule->getLabel());
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
intf_id_list.push_back( findInterfaceByNetzone( a ) );
|
||||||
|
} catch(string err)
|
||||||
|
{
|
||||||
|
// could not find interface with netzone to match address 'a'
|
||||||
|
// will assign rule to all interfaces. Act as if all interfaces
|
||||||
|
// had network zone 'any' and each matches this address.
|
||||||
|
|
||||||
|
// issue warning only if platform uses netwrk zones.
|
||||||
|
|
||||||
|
bool supports_network_zones =
|
||||||
|
Resources::getTargetCapabilityBool(
|
||||||
|
compiler->fw->getStr("platform"), "network_zones");
|
||||||
|
|
||||||
|
if (supports_network_zones) compiler->warning(err);
|
||||||
|
|
||||||
|
FWObjectTypedChildIterator i = compiler->fw->findByType(Interface::TYPENAME);
|
||||||
|
for ( ; i!=i.end(); ++i)
|
||||||
|
{
|
||||||
|
Interface *ifs = Interface::cast(*i);
|
||||||
|
intf_id_list.push_back( ifs->getId() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return intf_id_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
string triplet::hash()
|
||||||
|
{
|
||||||
|
return string(src->getAddress()) + "." +
|
||||||
|
string(dst->getAddress()) + "." +
|
||||||
|
srv->getId();
|
||||||
|
}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2002 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: Helper.h,v 1.1 2008/03/06 06:48:56 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
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __HELPER_HH
|
||||||
|
#define __HELPER_HH
|
||||||
|
|
||||||
|
#include <fwcompiler/Compiler.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include <fwbuilder/FWObject.h>
|
||||||
|
#include <fwbuilder/Address.h>
|
||||||
|
#include <fwbuilder/Firewall.h>
|
||||||
|
|
||||||
|
namespace fwcompiler {
|
||||||
|
|
||||||
|
class Helper
|
||||||
|
{
|
||||||
|
fwcompiler::Compiler *compiler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this methods checks if object addr belongs to network or address obj
|
||||||
|
*/
|
||||||
|
bool belongsTo(libfwbuilder::Address *obj,
|
||||||
|
const libfwbuilder::IPAddress &a);
|
||||||
|
bool belongsTo(libfwbuilder::Address *obj,
|
||||||
|
libfwbuilder::Address *addr);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Helper(fwcompiler::Compiler *comp) { compiler=comp; }
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* finds interface of the firewall to whose subnet object
|
||||||
|
* 'obj' belongs to. Returns interface ID
|
||||||
|
*/
|
||||||
|
std::string findInterfaceByAddress(const libfwbuilder::IPAddress &a);
|
||||||
|
std::string findInterfaceByAddress(libfwbuilder::Address *obj);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* finds interface of the firewall associated with the netzone
|
||||||
|
* that object 'obj' belongs to. Returns interface ID
|
||||||
|
*/
|
||||||
|
std::string findInterfaceByNetzone(const libfwbuilder::IPAddress &a)
|
||||||
|
throw(std::string);
|
||||||
|
std::string findInterfaceByNetzone(libfwbuilder::Address *obj);
|
||||||
|
std::list<std::string> findInterfaceByNetzoneOrAll(
|
||||||
|
libfwbuilder::RuleElement *re);
|
||||||
|
std::list<std::string> getAllInterfaceIDs();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* recursively expands object 'o' and places all its children
|
||||||
|
* objects in the list 'ol'. Uses cache in compiler.
|
||||||
|
*/
|
||||||
|
void expand_group_recursive(libfwbuilder::FWObject *o,
|
||||||
|
std::list<libfwbuilder::FWObject*> &ol);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* recursively expands object 'o' and places all its children
|
||||||
|
* objects in the list 'ol'. Does not use cache in compiler,
|
||||||
|
* therefore can be called even if compiler object has not
|
||||||
|
* been created yet.
|
||||||
|
*/
|
||||||
|
void expand_group_recursive_no_cache(libfwbuilder::FWObject *o,
|
||||||
|
std::list<libfwbuilder::FWObject*> &ol);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class triplet {
|
||||||
|
public:
|
||||||
|
libfwbuilder::Address *src;
|
||||||
|
libfwbuilder::Address *dst;
|
||||||
|
libfwbuilder::Service *srv;
|
||||||
|
triplet() {src=NULL; dst=NULL; srv=NULL;}
|
||||||
|
triplet(libfwbuilder::Address *s,
|
||||||
|
libfwbuilder::Address *d,
|
||||||
|
libfwbuilder::Service *v) {src=s; dst=d; srv=v;}
|
||||||
|
|
||||||
|
std::string hash();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,882 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2002 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: PolicyCompiler_cisco.cpp,v 1.1 2008/03/06 06:48:56 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 "config.h"
|
||||||
|
|
||||||
|
#include "PolicyCompiler_cisco.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;
|
||||||
|
|
||||||
|
string PolicyCompiler_cisco::myPlatformName() { return ""; }
|
||||||
|
|
||||||
|
PolicyCompiler_cisco::PolicyCompiler_cisco(FWObjectDatabase *_db,
|
||||||
|
const std::string &fwname,
|
||||||
|
OSConfigurator *_oscnf) :
|
||||||
|
PolicyCompiler(_db,fwname,_oscnf) , helper(this)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int PolicyCompiler_cisco::prolog()
|
||||||
|
{
|
||||||
|
return PolicyCompiler::prolog();
|
||||||
|
}
|
||||||
|
|
||||||
|
string PolicyCompiler_cisco::createRuleLabel(const string &txt,
|
||||||
|
Interface *iface,
|
||||||
|
int rule_num)
|
||||||
|
{
|
||||||
|
ostringstream str;
|
||||||
|
|
||||||
|
str << rule_num;
|
||||||
|
if (iface!=NULL) str << "(" << iface->getLabel() << ")";
|
||||||
|
else str << "(" << txt << ")";
|
||||||
|
return str.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string PolicyCompiler_cisco::debugPrintRule(Rule *r)
|
||||||
|
{
|
||||||
|
PolicyRule *rule=PolicyRule::cast(r);
|
||||||
|
Interface *rule_iface = getCachedFwInterface(rule->getInterfaceId());
|
||||||
|
string iname=(rule_iface!=NULL)?rule_iface->getName():"";
|
||||||
|
string dir= rule->getDirectionAsString();
|
||||||
|
|
||||||
|
return PolicyCompiler::debugPrintRule(rule)+
|
||||||
|
" "+dir+" "+iname+" "+rule->getStr("acl");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PolicyCompiler_cisco::addDefaultPolicyRule()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* set up backup ssh access to the firewall if told to do so
|
||||||
|
*/
|
||||||
|
if ( getCachedFwOpt()->getBool("mgmt_ssh") &&
|
||||||
|
!getCachedFwOpt()->getStr("mgmt_addr").empty() )
|
||||||
|
{
|
||||||
|
PolicyRule *r;
|
||||||
|
TCPService *ssh=TCPService::cast(dbcopy->create(TCPService::TYPENAME) );
|
||||||
|
ssh->setInt("dst_range_start",22);
|
||||||
|
ssh->setInt("dst_range_end",22);
|
||||||
|
dbcopy->add(ssh,false);
|
||||||
|
cacheObj(ssh); // to keep cache consistent
|
||||||
|
|
||||||
|
Network *mgmt_workstation = Network::cast(dbcopy->create(Network::TYPENAME));
|
||||||
|
*mgmt_workstation = getCachedFwOpt()->getStr("mgmt_addr");
|
||||||
|
dbcopy->add(mgmt_workstation,false);
|
||||||
|
cacheObj(mgmt_workstation); // to keep cache consistent
|
||||||
|
|
||||||
|
r= PolicyRule::cast(dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
temp_ruleset->add(r);
|
||||||
|
r->setAction(PolicyRule::Accept);
|
||||||
|
r->setLogging(false);
|
||||||
|
r->setDirection(PolicyRule::Inbound);
|
||||||
|
r->setPosition(-1);
|
||||||
|
r->setComment(" backup ssh access rule ");
|
||||||
|
r->setHidden(true);
|
||||||
|
r->setFallback(false);
|
||||||
|
r->setLabel("backup ssh access rule");
|
||||||
|
|
||||||
|
RuleElement *src=RuleElement::cast(
|
||||||
|
r->getFirstByType(RuleElementSrc::TYPENAME) );
|
||||||
|
src->addRef(mgmt_workstation);
|
||||||
|
|
||||||
|
RuleElement *dst=RuleElement::cast(
|
||||||
|
r->getFirstByType(RuleElementDst::TYPENAME) );
|
||||||
|
dst->addRef(fw);
|
||||||
|
|
||||||
|
RuleElement *srv=RuleElement::cast(
|
||||||
|
r->getFirstByType(RuleElementSrv::TYPENAME) );
|
||||||
|
srv->addRef(ssh);
|
||||||
|
|
||||||
|
combined_ruleset->push_front(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ciscos provide built-in fallback rule so we do not need
|
||||||
|
// this. Besides, desired behavior is that if the user did not
|
||||||
|
// create any rules for a given interface (at all), then generated
|
||||||
|
// config file should have none. Adding fallback rule here creates
|
||||||
|
// 'deny any any' rule for such interfaces and screws things big
|
||||||
|
// time.
|
||||||
|
#if 0
|
||||||
|
PolicyRule *r= PolicyRule::cast(dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
|
||||||
|
temp_ruleset->add(r);
|
||||||
|
r->setAction(PolicyRule::Deny);
|
||||||
|
r->setLogging(false);
|
||||||
|
// r->setDirection(PolicyRule::Both);
|
||||||
|
r->setPosition(10000);
|
||||||
|
r->setComment(" fallback rule ");
|
||||||
|
r->setLabel("fallback rule");
|
||||||
|
r->setFallback(true);
|
||||||
|
r->setHidden(true);
|
||||||
|
combined_ruleset->push_back(r);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyCompiler_cisco::splitIfSrcAny::processNext()
|
||||||
|
{
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
|
||||||
|
RuleElementSrc *srcrel=rule->getSrc();
|
||||||
|
Address *src = compiler->getFirstSrc(rule);
|
||||||
|
|
||||||
|
if ( rule->getDirection()!=PolicyRule::Inbound &&
|
||||||
|
(
|
||||||
|
srcrel->isAny() ||
|
||||||
|
|
||||||
|
( srcrel->size()==1 && src!=NULL &&
|
||||||
|
!compiler->complexMatch(src,compiler->fw) &&
|
||||||
|
srcrel->getBool("single_object_negation"))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
PolicyRule *r= PolicyRule::cast(
|
||||||
|
compiler->dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
compiler->temp_ruleset->add(r);
|
||||||
|
r->duplicate(rule);
|
||||||
|
r->setDirection( PolicyRule::Outbound );
|
||||||
|
|
||||||
|
RuleElementSrc *nsrc=r->getSrc();
|
||||||
|
nsrc->clearChildren();
|
||||||
|
nsrc->addRef(compiler->fw);
|
||||||
|
|
||||||
|
tmp_queue.push_back(r);
|
||||||
|
}
|
||||||
|
tmp_queue.push_back(rule); // add old rule anyway
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyCompiler_cisco::splitIfDstAny::processNext()
|
||||||
|
{
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
|
||||||
|
RuleElementSrv *srvrel=rule->getSrv();
|
||||||
|
RuleElementDst *dstrel=rule->getDst();
|
||||||
|
Address *dst=compiler->getFirstDst(rule);
|
||||||
|
|
||||||
|
|
||||||
|
std::list<FWObject*> cl;
|
||||||
|
for (list<FWObject*>::iterator i1=srvrel->begin(); i1!=srvrel->end(); ++i1)
|
||||||
|
{
|
||||||
|
FWObject *o = *i1;
|
||||||
|
FWObject *obj = NULL;
|
||||||
|
if (FWReference::cast(o)!=NULL) obj=FWReference::cast(o)->getPointer();
|
||||||
|
Service *s=Service::cast(obj);
|
||||||
|
assert(s!=NULL);
|
||||||
|
|
||||||
|
if (ICMPService::isA(s)) cl.push_back(s);
|
||||||
|
|
||||||
|
if (TCPService::isA(s) &&
|
||||||
|
s->getInt("dst_range_start")==22 &&
|
||||||
|
s->getInt("dst_range_end")==22) cl.push_back(s);
|
||||||
|
if (TCPService::isA(s) &&
|
||||||
|
s->getInt("dst_range_start")==23 &&
|
||||||
|
s->getInt("dst_range_end")==23) cl.push_back(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ( !cl.empty() && rule->getDirection()!=PolicyRule::Outbound &&
|
||||||
|
(
|
||||||
|
dstrel->isAny() ||
|
||||||
|
|
||||||
|
( dstrel->size()==1 && dst!=NULL &&
|
||||||
|
!compiler->complexMatch(dst,compiler->fw) &&
|
||||||
|
dstrel->getBool("single_object_negation"))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PolicyRule *r= PolicyRule::cast(
|
||||||
|
compiler->dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
compiler->temp_ruleset->add(r);
|
||||||
|
r->duplicate(rule);
|
||||||
|
r->setDirection( PolicyRule::Inbound );
|
||||||
|
|
||||||
|
RuleElementDst *ndst=r->getDst();
|
||||||
|
ndst->clearChildren();
|
||||||
|
ndst->addRef(compiler->fw);
|
||||||
|
|
||||||
|
RuleElementSrv *nsrv=r->getSrv();
|
||||||
|
nsrv->clearChildren();
|
||||||
|
for (list<FWObject*>::iterator i=cl.begin(); i!=cl.end(); ++i)
|
||||||
|
nsrv->addRef( (*i) );
|
||||||
|
|
||||||
|
tmp_queue.push_back(r);
|
||||||
|
}
|
||||||
|
tmp_queue.push_back(rule); // add old rule in any case
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool PolicyCompiler_cisco::NegationPhase1::processNext()
|
||||||
|
{
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
#ifdef DO_NEGATION
|
||||||
|
|
||||||
|
if (compiler->debug>=5) {
|
||||||
|
cerr << rule->getLabel() + " >>> neg 1 >>>>>>>>>>>>>>>>>>>>>>>>>>>>\n";
|
||||||
|
cerr << rule << " " << compiler->atomicRuleToString( rule );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RuleElementSrc *src=rule->getSrc(); assert(src);
|
||||||
|
RuleElementDst *dst=rule->getDst(); assert(dst);
|
||||||
|
RuleElementSrv *srv=rule->getSrv(); assert(srv);
|
||||||
|
|
||||||
|
|
||||||
|
/* do not use clearChildren because it
|
||||||
|
* destroys children objects (can delete
|
||||||
|
* rules created on the previous pass)
|
||||||
|
*/
|
||||||
|
compiler->temp_ruleset->clear();
|
||||||
|
|
||||||
|
if (src->getNeg()) {
|
||||||
|
|
||||||
|
PolicyRule *r= PolicyRule::cast(
|
||||||
|
getCompiler()->dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
compiler->temp_ruleset->add(r);
|
||||||
|
r->duplicate(rule);
|
||||||
|
r->setStr("action","CONTINUE");
|
||||||
|
|
||||||
|
RuleElementSrc *nsrc=r->getSrc();
|
||||||
|
nsrc->setNeg(false);
|
||||||
|
vr->push_back(r);
|
||||||
|
|
||||||
|
r= PolicyRule::cast(
|
||||||
|
getCompiler()->dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
compiler->temp_ruleset->add(r);
|
||||||
|
r->duplicate(rule);
|
||||||
|
|
||||||
|
nsrc=r->getSrc();
|
||||||
|
nsrc->clearChildren();
|
||||||
|
nsrc->setAnyElement();
|
||||||
|
nsrc->setNeg(false);
|
||||||
|
vr->push_back(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dst->getNeg()) {
|
||||||
|
|
||||||
|
PolicyRule *r= PolicyRule::cast(
|
||||||
|
getCompiler()->dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
compiler->temp_ruleset->add(r);
|
||||||
|
r->duplicate(rule);
|
||||||
|
r->setStr("action","CONTINUE");
|
||||||
|
|
||||||
|
RuleElementDst *ndst=r->getDst();;
|
||||||
|
ndst->setNeg(false);
|
||||||
|
vr->push_back(r);
|
||||||
|
|
||||||
|
r= PolicyRule::cast(
|
||||||
|
getCompiler()->dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
compiler->temp_ruleset->add(r);
|
||||||
|
r->duplicate(rule);
|
||||||
|
|
||||||
|
ndst=r->getDst();;
|
||||||
|
ndst->clearChildren();
|
||||||
|
ndst->setAnyElement();
|
||||||
|
ndst->setNeg(false);
|
||||||
|
vr->push_back(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srv->getNeg()) {
|
||||||
|
|
||||||
|
PolicyRule *r= PolicyRule::cast(
|
||||||
|
getCompiler()->dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
compiler->temp_ruleset->add(r);
|
||||||
|
r->duplicate(rule);
|
||||||
|
r->setStr("action","CONTINUE");
|
||||||
|
|
||||||
|
RuleElementSrv *nsrv=r->getSrv();
|
||||||
|
nsrv->setNeg(false);
|
||||||
|
vr->push_back(r);
|
||||||
|
|
||||||
|
r= PolicyRule::cast(
|
||||||
|
getCompiler()->dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
compiler->temp_ruleset->add(r);
|
||||||
|
r->duplicate(rule);
|
||||||
|
|
||||||
|
nsrv=r->getSrv();
|
||||||
|
nsrv->clearChildren();
|
||||||
|
nsrv->setAnyElement();
|
||||||
|
nsrv->setNeg(false);
|
||||||
|
vr->push_back(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vr->empty()) {
|
||||||
|
PolicyRule *r= PolicyRule::cast(
|
||||||
|
getCompiler()->dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
compiler->temp_ruleset->add(r);
|
||||||
|
|
||||||
|
if (compiler->debug>=5) {
|
||||||
|
cerr << "****************** copying rule\n";
|
||||||
|
rule->dump(true,true);
|
||||||
|
}
|
||||||
|
r->duplicate(rule);
|
||||||
|
vr->push_back(r);
|
||||||
|
}
|
||||||
|
if (compiler->debug>=5) {
|
||||||
|
cerr << rule->getLabel() + " <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n";
|
||||||
|
rule->dump(true,true);
|
||||||
|
cerr << " ------------------------------------------------\n";
|
||||||
|
|
||||||
|
for (vector<Rule*>::iterator i=vr->begin(); i!=vr->end(); i++) {
|
||||||
|
Rule *r=(*i);
|
||||||
|
r->dump(true,true);
|
||||||
|
cerr << r << " " << compiler->atomicRuleToString( r );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* re_type can be either RuleElementSrc::TYPENAME or RuleElementDst::TYPENAME
|
||||||
|
*
|
||||||
|
* TODO: this has to move to class PolicyRuleProcessor
|
||||||
|
*/
|
||||||
|
bool PolicyCompiler_cisco::splitIfRuleElementMatchesFW::processNext()
|
||||||
|
{
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
PolicyCompiler_cisco *cisco_comp=dynamic_cast<PolicyCompiler_cisco*>(compiler);
|
||||||
|
|
||||||
|
RuleElement *re=RuleElement::cast(rule->getFirstByType(re_type));
|
||||||
|
int nre=re->size();
|
||||||
|
|
||||||
|
list<FWObject*> cl;
|
||||||
|
|
||||||
|
for (list<FWObject*>::iterator i1=re->begin(); nre>1 && i1!=re->end(); ++i1)
|
||||||
|
{
|
||||||
|
FWObject *o = *i1;
|
||||||
|
FWObject *obj = NULL;
|
||||||
|
if (FWReference::cast(o)!=NULL) obj=FWReference::cast(o)->getPointer();
|
||||||
|
Address *a=Address::cast(obj);
|
||||||
|
assert(a!=NULL);
|
||||||
|
|
||||||
|
// IPAddress obj_addr=a->getAddress();
|
||||||
|
|
||||||
|
if (cisco_comp->complexMatch(a,cisco_comp->fw)) {
|
||||||
|
|
||||||
|
cl.push_back(o); // can not remove right now because remove invalidates iterator
|
||||||
|
nre--;
|
||||||
|
|
||||||
|
PolicyRule *new_rule= PolicyRule::cast(compiler->dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
compiler->temp_ruleset->add(new_rule);
|
||||||
|
new_rule->duplicate(rule);
|
||||||
|
RuleElement *new_re=RuleElement::cast(new_rule->getFirstByType(re_type));
|
||||||
|
new_re->clearChildren();
|
||||||
|
new_re->setAnyElement();
|
||||||
|
new_re->addRef( a );
|
||||||
|
tmp_queue.push_back(new_rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (!cl.empty())
|
||||||
|
{
|
||||||
|
for (list<FWObject*>::iterator i1=cl.begin(); i1!=cl.end(); ++i1)
|
||||||
|
re->remove( (*i1) );
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyCompiler_cisco::specialCaseWithDynInterface::dropDynamicInterface(
|
||||||
|
PolicyRule *rule, PolicyRule::Direction cmp_dir, RuleElement *re)
|
||||||
|
{
|
||||||
|
PolicyRule::Direction dir=rule->getDirection();
|
||||||
|
Interface *rule_iface = compiler->getCachedFwInterface(rule->getInterfaceId());
|
||||||
|
|
||||||
|
list<FWObject*> cl;
|
||||||
|
for (list<FWObject*>::iterator i1=re->begin(); i1!=re->end(); ++i1)
|
||||||
|
{
|
||||||
|
FWObject *o = *i1;
|
||||||
|
FWObject *obj = o;
|
||||||
|
if (FWReference::cast(o)!=NULL) obj=FWReference::cast(o)->getPointer();
|
||||||
|
Interface *ifs =Interface::cast( obj );
|
||||||
|
|
||||||
|
if (ifs!=NULL && ifs->isDyn())
|
||||||
|
{
|
||||||
|
if (ifs->getId()==rule_iface->getId() && dir==cmp_dir)
|
||||||
|
cl.push_back(obj); // keep it
|
||||||
|
else
|
||||||
|
continue; // remove it
|
||||||
|
} else
|
||||||
|
cl.push_back(obj);
|
||||||
|
}
|
||||||
|
if (re->size()==1 && cl.empty()) // remove the whole rule
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!cl.empty())
|
||||||
|
{
|
||||||
|
re->clearChildren();
|
||||||
|
for (list<FWObject*>::iterator i1=cl.begin(); i1!=cl.end(); ++i1)
|
||||||
|
{
|
||||||
|
FWObject *oo = *i1;
|
||||||
|
re->addRef( oo );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks for the following situations:
|
||||||
|
*
|
||||||
|
* assuming interface 'INT' is dynamic
|
||||||
|
*
|
||||||
|
* src. rule bound to interface direction decision
|
||||||
|
* -----------------------------------------------------------------
|
||||||
|
* INT INT outbound keep
|
||||||
|
* INT any other outbound remove
|
||||||
|
* INT INT inbound remove
|
||||||
|
* INT any other inbound remove
|
||||||
|
*
|
||||||
|
* dest. rule bound to interface direction decision
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* INT INT inbound keep
|
||||||
|
* INT any other inbound remove
|
||||||
|
* INT INT outbound remove
|
||||||
|
* INT any other outbound remove
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool PolicyCompiler_cisco::specialCaseWithDynInterface::processNext()
|
||||||
|
{
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
|
||||||
|
if ( dropDynamicInterface( rule, PolicyRule::Outbound, rule->getSrc() ) &&
|
||||||
|
dropDynamicInterface( rule, PolicyRule::Inbound, rule->getDst() ) )
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* processor splitIfRuleElementMatchesFW (or one derived from it)
|
||||||
|
* should have been called before tcpServiceToFW. This way we know
|
||||||
|
* that if dst is a firewall, it is a single object there.
|
||||||
|
*/
|
||||||
|
bool PolicyCompiler_cisco::tcpServiceToFW::processNext()
|
||||||
|
{
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
PolicyCompiler_cisco *cisco_comp=dynamic_cast<PolicyCompiler_cisco*>(compiler);
|
||||||
|
// RuleElementSrc *src=rule->getSrc();
|
||||||
|
// RuleElementDst *dst=rule->getDst();
|
||||||
|
RuleElementSrv *srv=rule->getSrv();
|
||||||
|
Address *a=compiler->getFirstDst(rule);
|
||||||
|
assert(a!=NULL);
|
||||||
|
|
||||||
|
if (rule->getAction()==PolicyRule::Accept &&
|
||||||
|
compiler->complexMatch(a,cisco_comp->fw))
|
||||||
|
{
|
||||||
|
std::list<FWObject*> cl;
|
||||||
|
for (list<FWObject*>::iterator i1=srv->begin(); i1!=srv->end(); ++i1)
|
||||||
|
{
|
||||||
|
FWObject *o = *i1;
|
||||||
|
FWObject *obj = NULL;
|
||||||
|
if (FWReference::cast(o)!=NULL) obj=FWReference::cast(o)->getPointer();
|
||||||
|
Service *s=Service::cast(obj);
|
||||||
|
assert(s!=NULL);
|
||||||
|
|
||||||
|
if (TCPService::isA(s) &&
|
||||||
|
s->getInt("dst_range_start")==port &&
|
||||||
|
s->getInt("dst_range_end")==port) cl.push_back(o);
|
||||||
|
}
|
||||||
|
if (!cl.empty())
|
||||||
|
{
|
||||||
|
|
||||||
|
PolicyRule *r= PolicyRule::cast(compiler->dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
compiler->temp_ruleset->add(r);
|
||||||
|
r->duplicate(rule);
|
||||||
|
RuleElementDst *ndst=r->getDst();
|
||||||
|
ndst->clearChildren();
|
||||||
|
ndst->setAnyElement();
|
||||||
|
// ndst->addRef( compiler->fw );
|
||||||
|
RuleElementSrv *nsrv=r->getSrv();
|
||||||
|
nsrv->clearChildren();
|
||||||
|
nsrv->add( cl.front() );
|
||||||
|
r->setBool("ssh_telnet_cmd",true);
|
||||||
|
tmp_queue.push_back(r);
|
||||||
|
|
||||||
|
for (list<FWObject*>::iterator i1=cl.begin(); i1!=cl.end(); ++i1)
|
||||||
|
srv->remove( (*i1) );
|
||||||
|
|
||||||
|
if (srv->size()>0)
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
} else
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
} else
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* firewall should be a single object in SRC. If object in SRC matches
|
||||||
|
* firewall (in a sence of complexMatch) but is not actual firewall object,
|
||||||
|
* do nothing assuming user wanted it that way.
|
||||||
|
*/
|
||||||
|
bool PolicyCompiler_cisco::replaceFWinSRCInterfacePolicy::processNext()
|
||||||
|
{
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
Interface *rule_iface = compiler->getCachedFwInterface(rule->getInterfaceId());
|
||||||
|
|
||||||
|
if (rule_iface!=NULL && rule->getDirection()==PolicyRule::Outbound)
|
||||||
|
{
|
||||||
|
RuleElementSrc *src=rule->getSrc();
|
||||||
|
|
||||||
|
if (compiler->getFirstSrc(rule)->getId()==compiler->fw->getId())
|
||||||
|
{
|
||||||
|
src->clearChildren();
|
||||||
|
src->addRef(rule_iface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyCompiler_cisco::replaceFWinDSTInterfacePolicy::processNext()
|
||||||
|
{
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
Interface *rule_iface = compiler->getCachedFwInterface(rule->getInterfaceId());
|
||||||
|
|
||||||
|
if (rule_iface!=NULL && rule->getDirection()==PolicyRule::Inbound)
|
||||||
|
{
|
||||||
|
RuleElementDst *dst=rule->getDst();
|
||||||
|
|
||||||
|
if (compiler->getFirstDst(rule)->getId()==compiler->fw->getId())
|
||||||
|
{
|
||||||
|
dst->clearChildren();
|
||||||
|
dst->addRef(rule_iface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dst should contain objects that belong to the network zone of the
|
||||||
|
* same interface (use splitByNetworkZonesForRE for that)
|
||||||
|
*/
|
||||||
|
bool PolicyCompiler_cisco::replaceFWinDSTPolicy::processNext()
|
||||||
|
{
|
||||||
|
Helper helper(compiler);
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
Interface *rule_iface = compiler->getCachedFwInterface(rule->getInterfaceId());
|
||||||
|
|
||||||
|
if (rule_iface==NULL)
|
||||||
|
{
|
||||||
|
RuleElementSrc *src=rule->getSrc();
|
||||||
|
RuleElementDst *dst=rule->getDst();
|
||||||
|
|
||||||
|
if (!src->isAny() && compiler->getFirstDst(rule)->getId()==compiler->fw->getId())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string iface_id=helper.findInterfaceByNetzone(compiler->getFirstSrc(rule));
|
||||||
|
Interface *iface = compiler->getCachedFwInterface(iface_id);
|
||||||
|
|
||||||
|
dst->clearChildren();
|
||||||
|
dst->addRef(iface);
|
||||||
|
} catch (string addr)
|
||||||
|
{
|
||||||
|
ostringstream str;
|
||||||
|
str << "Address " << addr
|
||||||
|
<< " does not match address or network zone of any interface. Rule "
|
||||||
|
<< rule->getLabel()
|
||||||
|
<< endl;
|
||||||
|
compiler->abort(str.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolicyCompiler_cisco::splitByNetworkZonesForRE::AddToInterface(
|
||||||
|
const std::string &interface_id,
|
||||||
|
libfwbuilder::Address *addr,
|
||||||
|
PolicyRule *rule)
|
||||||
|
{
|
||||||
|
PolicyRule *new_rule;
|
||||||
|
RuleElement *new_re;
|
||||||
|
|
||||||
|
new_rule=rules[interface_id];
|
||||||
|
if (new_rule==NULL)
|
||||||
|
{
|
||||||
|
new_rule= PolicyRule::cast(compiler->dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
compiler->temp_ruleset->add(new_rule);
|
||||||
|
new_rule->duplicate(rule);
|
||||||
|
rules[interface_id]=new_rule;
|
||||||
|
new_re=RuleElement::cast(new_rule->getFirstByType(re_type));
|
||||||
|
new_re->clearChildren();
|
||||||
|
new_re->setAnyElement();
|
||||||
|
}
|
||||||
|
new_re=RuleElement::cast(new_rule->getFirstByType(re_type));
|
||||||
|
new_re->addRef( addr );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyCompiler_cisco::splitByNetworkZonesForRE::processNext()
|
||||||
|
{
|
||||||
|
Helper helper(compiler);
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
RuleElement *re=RuleElement::cast(rule->getFirstByType(re_type));
|
||||||
|
if (re->size()==1)
|
||||||
|
{
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
rules.clear();
|
||||||
|
|
||||||
|
std::list<FWObject*> cl;
|
||||||
|
for (list<FWObject*>::iterator i1=re->begin(); i1!=re->end(); ++i1)
|
||||||
|
{
|
||||||
|
FWObject *o = *i1;
|
||||||
|
FWObject *obj = NULL;
|
||||||
|
if (FWReference::cast(o)!=NULL) obj=FWReference::cast(o)->getPointer();
|
||||||
|
Address *a=Address::cast(obj);
|
||||||
|
assert(a!=NULL);
|
||||||
|
|
||||||
|
// IPAddress obj_addr=a->getAddress();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string interface_id=helper.findInterfaceByNetzone(a);
|
||||||
|
AddToInterface(interface_id, a, rule);
|
||||||
|
} catch (string err)
|
||||||
|
{
|
||||||
|
// could not find interface with netzone to match address 'a'
|
||||||
|
// will assign rule to all interfaces. Act as if all interfaces
|
||||||
|
// had network zone 'any' and each matches this address.
|
||||||
|
|
||||||
|
// issue warning only if platform uses netwrk zones.
|
||||||
|
|
||||||
|
bool supports_network_zones =
|
||||||
|
Resources::getTargetCapabilityBool(
|
||||||
|
compiler->fw->getStr("platform"), "network_zones");
|
||||||
|
|
||||||
|
if (supports_network_zones)
|
||||||
|
compiler->warning(err + " Rule " + rule->getLabel());
|
||||||
|
|
||||||
|
FWObjectTypedChildIterator i =
|
||||||
|
compiler->fw->findByType(Interface::TYPENAME);
|
||||||
|
for ( ; i!=i.end(); ++i)
|
||||||
|
{
|
||||||
|
Interface *ifs = Interface::cast(*i);
|
||||||
|
AddToInterface(ifs->getId(), a, rule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (std::map<std::string,PolicyRule*>::iterator i=rules.begin();
|
||||||
|
i!=rules.end(); ++i)
|
||||||
|
{
|
||||||
|
tmp_queue.push_back((*i).second);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyCompiler_cisco::equalObjCISCO::operator()(FWObject *o)
|
||||||
|
{
|
||||||
|
if (ICMPService::cast(obj)!=NULL && ICMPService::cast(o)!=NULL)
|
||||||
|
{
|
||||||
|
return (obj->getInt("type")==o->getInt("type"));
|
||||||
|
} else
|
||||||
|
return o->getId()==obj->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* re_type can be either RuleElementSrc::TYPENAME or RuleElementDst::TYPENAME */
|
||||||
|
bool PolicyCompiler_cisco::removeRedundantAddresses::processNext()
|
||||||
|
{
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
|
||||||
|
RuleElement *re=RuleElement::cast(rule->getFirstByType(re_type));
|
||||||
|
if (re->size()==1)
|
||||||
|
{
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<Address*,FWObject*> addrmap;
|
||||||
|
std::list<FWObject*> cl;
|
||||||
|
for (list<FWObject*>::iterator i1=re->begin(); i1!=re->end(); ++i1)
|
||||||
|
{
|
||||||
|
FWObject *obj = *i1;
|
||||||
|
if (FWReference::cast(obj)!=NULL) obj=FWReference::cast(obj)->getPointer();
|
||||||
|
Address *a=Address::cast(obj);
|
||||||
|
assert(a!=NULL); // assuming all objects are addresses.
|
||||||
|
addrmap[a] = *i1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::map<Address*,FWObject*>::iterator i1=addrmap.begin();
|
||||||
|
i1!=addrmap.end(); ++i1)
|
||||||
|
{
|
||||||
|
Address *a1 = i1->first;
|
||||||
|
|
||||||
|
for (std::map<Address*,FWObject*>::iterator i2=addrmap.begin();
|
||||||
|
i2!=addrmap.end(); ++i2)
|
||||||
|
{
|
||||||
|
Address *a2 = i2->first;
|
||||||
|
if (a1==a2) continue;
|
||||||
|
if (fwcompiler::checkForShadowing(*a1, *a2) ) cl.push_back(i1->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cl.empty()) {
|
||||||
|
for (list<FWObject*>::iterator i1=cl.begin(); i1!=cl.end(); ++i1)
|
||||||
|
re->remove( (*i1) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyCompiler_cisco::processMultiAddressObjectsInRE::processNext()
|
||||||
|
{
|
||||||
|
PolicyRule *rule = getNext(); if (rule==NULL) return false;
|
||||||
|
RuleElement *re = RuleElement::cast( rule->getFirstByType(re_type) );
|
||||||
|
|
||||||
|
for (FWObject::iterator i=re->begin(); i!=re->end(); i++)
|
||||||
|
{
|
||||||
|
FWObject *o = *i;
|
||||||
|
if (FWReference::cast(o)!=NULL) o = FWReference::cast(o)->getPointer();
|
||||||
|
MultiAddress *atrt = MultiAddress::cast(o);
|
||||||
|
if (atrt!=NULL && atrt->isRunTime())
|
||||||
|
compiler->abort("Run-time AddressTable and DNSName objects are not supported. Rule " + rule->getLabel());
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PolicyCompiler_cisco::compile()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
class acl_sort_order
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
acl_sort_order() {};
|
||||||
|
bool operator()(const string &a, const string &b)
|
||||||
|
{
|
||||||
|
string::size_type i1,i2;
|
||||||
|
i1=a.find(' ',a.find(' ')+1);
|
||||||
|
i2=b.find(' ',b.find(' ')+1);
|
||||||
|
return a.substr(0,i1) < b.substr(0,i2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void PolicyCompiler_cisco::regroup()
|
||||||
|
{
|
||||||
|
list<string> commands;
|
||||||
|
map<string,list<string> > script;
|
||||||
|
|
||||||
|
commands.push_back("THE_REST");
|
||||||
|
commands.push_back("access-list ");
|
||||||
|
commands.push_back("access-group ");
|
||||||
|
commands.push_back("icmp ");
|
||||||
|
commands.push_back("ssh ");
|
||||||
|
commands.push_back("telnet ");
|
||||||
|
|
||||||
|
string acl, agrp, icmp, telnet, ssh;
|
||||||
|
string new_output;
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
|
istringstream in(output.str());
|
||||||
|
|
||||||
|
while (in)
|
||||||
|
{
|
||||||
|
in.getline(buf, 1023, '\n');
|
||||||
|
|
||||||
|
strcat(buf,"\n");
|
||||||
|
|
||||||
|
if (buf[0]=='!') continue;
|
||||||
|
|
||||||
|
string slot="THE_REST";
|
||||||
|
string cmd(buf);
|
||||||
|
string::size_type n=cmd.find(' ');
|
||||||
|
|
||||||
|
list<string>::iterator s = ::find(commands.begin(),commands.end(),cmd.substr(0,n+1));
|
||||||
|
if (s!=commands.end()) slot = *s;
|
||||||
|
|
||||||
|
script[slot].push_back(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
script["access-list "].sort(acl_sort_order());
|
||||||
|
|
||||||
|
output.str("");
|
||||||
|
|
||||||
|
for (list<string>::iterator i=commands.begin(); i!=commands.end(); ++i)
|
||||||
|
{
|
||||||
|
for (list<string>::iterator j=script[*i].begin(); j!=script[*i].end(); ++j)
|
||||||
|
output << *j;
|
||||||
|
output << "! \n";
|
||||||
|
output << "! \n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolicyCompiler_cisco::epilog()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,460 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2002 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: PolicyCompiler_cisco.h,v 1.1 2008/03/06 06:48:56 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
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __POLICYCOMPILER_CISCO_HH
|
||||||
|
#define __POLICYCOMPILER_CISCO_HH
|
||||||
|
|
||||||
|
#include <fwbuilder/libfwbuilder-config.h>
|
||||||
|
|
||||||
|
#include "fwcompiler/PolicyCompiler.h"
|
||||||
|
#include "fwbuilder/RuleElement.h"
|
||||||
|
|
||||||
|
#include "Helper.h"
|
||||||
|
#include "ACL.h"
|
||||||
|
|
||||||
|
namespace libfwbuilder {
|
||||||
|
class IPService;
|
||||||
|
class ICMPService;
|
||||||
|
class TCPService;
|
||||||
|
class UDPService;
|
||||||
|
class RuleElementSrc;
|
||||||
|
class RuleElementDst;
|
||||||
|
class RuleElementSrv;
|
||||||
|
class Group;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace fwcompiler {
|
||||||
|
|
||||||
|
class PolicyCompiler_cisco : public PolicyCompiler {
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* our firewall policy must block everything by default even
|
||||||
|
* if there are no rules. In iptables we do this by setting
|
||||||
|
* default chain policies to DROP. Here we do this by adding
|
||||||
|
* this unconditional blocking rule in the end. See also comment
|
||||||
|
* in the code regarding "pass_all_out" option
|
||||||
|
*/
|
||||||
|
void addDefaultPolicyRule();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prints rule in some universal format (close to that visible
|
||||||
|
* to user in the GUI). Used for debugging purposes. This method
|
||||||
|
* calls PolicyCompiler::_internalPrintPolicyRule and then adds
|
||||||
|
* fields specific to PIX rules at the end of the printout
|
||||||
|
*/
|
||||||
|
virtual std::string debugPrintRule(libfwbuilder::Rule *rule);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drops dynamic interface from the rule in the following
|
||||||
|
* cases because its address is unknown and we can not build
|
||||||
|
* ACL rule for it.
|
||||||
|
*
|
||||||
|
* assuming interface 'INT' is dynamic
|
||||||
|
*
|
||||||
|
* src. rule bound to interface direction decision
|
||||||
|
* -----------------------------------------------------------------
|
||||||
|
* INT INT outbound keep
|
||||||
|
* INT any other outbound remove
|
||||||
|
* INT INT inbound remove
|
||||||
|
* INT any other inbound remove
|
||||||
|
*
|
||||||
|
* dest. rule bound to interface direction decision
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
* INT INT inbound keep
|
||||||
|
* INT any other inbound remove
|
||||||
|
* INT INT outbound remove
|
||||||
|
* INT any other outbound remove
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
friend class specialCaseWithDynInterface;
|
||||||
|
class specialCaseWithDynInterface : public PolicyRuleProcessor
|
||||||
|
{
|
||||||
|
bool dropDynamicInterface(libfwbuilder::PolicyRule *rule,
|
||||||
|
libfwbuilder::PolicyRule::Direction dir,
|
||||||
|
libfwbuilder::RuleElement *re);
|
||||||
|
public:
|
||||||
|
specialCaseWithDynInterface(const std::string &name) : PolicyRuleProcessor(name) {}
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* only for rules with interface element 'all' and direction
|
||||||
|
* 'both' or 'inbound'; for interfaces with zones that match
|
||||||
|
* src: create rule with that interface, direction
|
||||||
|
* inbound. 'Any' in src matches all interfaces.
|
||||||
|
*
|
||||||
|
* Set flag (boolean) 'interface_and_direction_set_from_src'
|
||||||
|
* so other rule processors in the same batch can skip the
|
||||||
|
* rule.
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( setInterfaceAndDirectionBySrc );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* only for rules with interface element 'all'and direction
|
||||||
|
* 'both' or 'outbound'; for interfaces with zones that match
|
||||||
|
* dst: create rule with that interface, direction
|
||||||
|
* outbound. 'Any' in dst matches all interfaces.
|
||||||
|
*
|
||||||
|
* Set flag (boolean) 'interface_and_direction_set_from_dst'
|
||||||
|
* so other rule processors in the same batch can skip the
|
||||||
|
* rule.
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( setInterfaceAndDirectionByDst );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* for rules with interface element not 'all' and direction
|
||||||
|
* 'both': create two rules with the same interface and
|
||||||
|
* directions Inbound and Outbound
|
||||||
|
*
|
||||||
|
* for rules with interface element not 'all' and direction
|
||||||
|
* 'inbound' or 'outbound': setInterfaceId to this interface
|
||||||
|
*
|
||||||
|
* Skip rule if flag 'interface_and_direction_set_from_src' or
|
||||||
|
* 'interface_and_direction_set_from_dst' is set
|
||||||
|
*
|
||||||
|
* Set flag (boolean) 'interface_and_direction_set'
|
||||||
|
* so other rule processors in the same batch can skip the
|
||||||
|
* rule.
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( setInterfaceAndDirectionIfInterfaceSet );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* determine acl rules should belong to
|
||||||
|
*/
|
||||||
|
class pickACL : public PolicyRuleProcessor
|
||||||
|
{
|
||||||
|
bool using_named_acl;
|
||||||
|
public:
|
||||||
|
pickACL(bool use_named_acl,const std::string &name) :
|
||||||
|
PolicyRuleProcessor(name) {using_named_acl = use_named_acl;}
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
friend class PolicyCompiler_cisco::pickACL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* split rule if Src==any
|
||||||
|
*
|
||||||
|
* This is special case since we assume that "any" includes
|
||||||
|
* also a firewall object. Packets headed to or from the
|
||||||
|
* firewall must be inspected by INPUT or OUTPUT chain, while
|
||||||
|
* packets crossing the firewall are inspected by FORWARD
|
||||||
|
* chain. If we assume that "any" also includes firewall
|
||||||
|
* itself, then we need to generate code for both FORWARD and
|
||||||
|
* INPUT/OUTPUT chains from the same rule. This processor
|
||||||
|
* splits the rule onto two and sets chain and direction in
|
||||||
|
* the second copy appropriately. It preserve original src and
|
||||||
|
* dst in both copies, it only changes chain and direction in
|
||||||
|
* the second copy.
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR(splitIfSrcAny);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* split rule if Dst==any. See comment in splitIfSrcAny
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR(splitIfDstAny);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: move this processor to class PolicyCompiler. The same
|
||||||
|
* processor is used in ipt and in pf (although in pf there it
|
||||||
|
* is present in two copies that have different names
|
||||||
|
* splitIfFirewallInSrc and splitIfFirewallInDst). Move also
|
||||||
|
* splitIfSrcMatchesFw and splitIfDstMatchesFw
|
||||||
|
*/
|
||||||
|
friend class splitIfRuleElementMatchesFW;
|
||||||
|
class splitIfRuleElementMatchesFW : public PolicyRuleProcessor
|
||||||
|
{
|
||||||
|
std::string re_type;
|
||||||
|
public:
|
||||||
|
splitIfRuleElementMatchesFW(const std::string &n,
|
||||||
|
std::string _type) :
|
||||||
|
PolicyRuleProcessor(n) { re_type=_type; }
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
|
||||||
|
friend class splitIfSrcMatchesFw;
|
||||||
|
class splitIfSrcMatchesFw : public splitIfRuleElementMatchesFW
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
splitIfSrcMatchesFw (const std::string &n) :
|
||||||
|
splitIfRuleElementMatchesFW(n,libfwbuilder::RuleElementSrc::TYPENAME) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class splitIfDstMatchesFw : public splitIfRuleElementMatchesFW
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
splitIfDstMatchesFw (const std::string &n) :
|
||||||
|
splitIfRuleElementMatchesFW(n,libfwbuilder::RuleElementDst::TYPENAME) {}
|
||||||
|
};
|
||||||
|
friend class PolicyCompiler_cisco::splitIfDstMatchesFw;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find redundant objects in rule element and eliminate
|
||||||
|
* them. This only works for SRC and DST since all objects are
|
||||||
|
* assumed to be addresses. Redundant object is such that has
|
||||||
|
* narrower address range than some other object in the same
|
||||||
|
* rule element.
|
||||||
|
*/
|
||||||
|
friend class removeRedundantAddresses;
|
||||||
|
class removeRedundantAddresses : public PolicyRuleProcessor
|
||||||
|
{
|
||||||
|
std::string re_type;
|
||||||
|
public:
|
||||||
|
removeRedundantAddresses(const std::string &n,std::string _type) :
|
||||||
|
PolicyRuleProcessor(n) { re_type=_type; }
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
|
||||||
|
friend class removeRedundantAddressesFromSrc;
|
||||||
|
class removeRedundantAddressesFromSrc : public removeRedundantAddresses
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
removeRedundantAddressesFromSrc (const std::string &n) :
|
||||||
|
removeRedundantAddresses(n,libfwbuilder::RuleElementSrc::TYPENAME) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
friend class removeRedundantAddressesFromDst;
|
||||||
|
class removeRedundantAddressesFromDst : public removeRedundantAddresses
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
removeRedundantAddressesFromDst (const std::string &n) :
|
||||||
|
removeRedundantAddresses(n,libfwbuilder::RuleElementDst::TYPENAME) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this processor splits rules if it finds rule that controls
|
||||||
|
* access for tcp service with port number "port" to the firewall
|
||||||
|
*/
|
||||||
|
class tcpServiceToFW : public PolicyRuleProcessor
|
||||||
|
{
|
||||||
|
int port;
|
||||||
|
public:
|
||||||
|
tcpServiceToFW(int p,const std::string &name) :
|
||||||
|
PolicyRuleProcessor(name) {port=p;}
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
friend class PolicyCompiler_cisco::tcpServiceToFW;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this processor splits rules if it finds telnet to firewall
|
||||||
|
*/
|
||||||
|
class telnetToFirewall : public tcpServiceToFW
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
telnetToFirewall(const std::string &n):tcpServiceToFW(23,n) {}
|
||||||
|
};
|
||||||
|
friend class telnetToFirewall;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this processor splits rules if it finds ssh to firewall
|
||||||
|
*/
|
||||||
|
class sshToFirewall : public tcpServiceToFW
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
sshToFirewall(const std::string &n):tcpServiceToFW(22,n) {}
|
||||||
|
};
|
||||||
|
friend class sshToFirewall;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* replace fw with one of its interfaces in SRC in interface
|
||||||
|
* policy rule
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( replaceFWinSRCInterfacePolicy );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* replace fw with one of its interfaces in DST in interface
|
||||||
|
* policy rule
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( replaceFWinDSTInterfacePolicy );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* replace fw with one of its interfaces in DST in global
|
||||||
|
* policy rule
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( replaceFWinDSTPolicy );
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this processor splits rules if objects in rule element
|
||||||
|
* re_type belong to different network zones
|
||||||
|
*/
|
||||||
|
class splitByNetworkZonesForRE : public PolicyRuleProcessor
|
||||||
|
{
|
||||||
|
std::string re_type;
|
||||||
|
std::map<std::string,libfwbuilder::PolicyRule*> rules;
|
||||||
|
void AddToInterface(const std::string &interface_id,
|
||||||
|
libfwbuilder::Address *addr,
|
||||||
|
libfwbuilder::PolicyRule *rule);
|
||||||
|
public:
|
||||||
|
splitByNetworkZonesForRE(const std::string &name,const std::string &_type) :
|
||||||
|
PolicyRuleProcessor(name) {re_type=_type; }
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class splitByNetworkZonesForSrc : public splitByNetworkZonesForRE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
splitByNetworkZonesForSrc(const std::string &n):
|
||||||
|
splitByNetworkZonesForRE(n,libfwbuilder::RuleElementSrc::TYPENAME) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class splitByNetworkZonesForDst : public splitByNetworkZonesForRE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
splitByNetworkZonesForDst(const std::string &n):
|
||||||
|
splitByNetworkZonesForRE(n,libfwbuilder::RuleElementDst::TYPENAME) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this processor deals with negation in all fields by
|
||||||
|
* splitting the rule and using temporary action
|
||||||
|
* "CONTINUE". Rules must be filtered through NegationPhase2
|
||||||
|
* later
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( NegationPhase1 );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* eliminates duplicate objects in rule element
|
||||||
|
* 're_type'. Uses special comparison function class to
|
||||||
|
* detect equivalent ICMP objects
|
||||||
|
*/
|
||||||
|
class equalObjCISCO : public PolicyCompiler::equalObj
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual bool operator()(libfwbuilder::FWObject *o);
|
||||||
|
};
|
||||||
|
|
||||||
|
class eliminateDuplicatesInRE_cisco : public PolicyCompiler::eliminateDuplicatesInRE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
eliminateDuplicatesInRE_cisco(const std::string &n,const std::string &re_type) :
|
||||||
|
eliminateDuplicatesInRE(n,re_type) { comparator=new equalObjCISCO(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* eliminates duplicate objects in SRC.
|
||||||
|
*/
|
||||||
|
class eliminateDuplicatesInSRC : public eliminateDuplicatesInRE_cisco
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
eliminateDuplicatesInSRC(const std::string &n) :
|
||||||
|
eliminateDuplicatesInRE_cisco(n,libfwbuilder::RuleElementSrc::TYPENAME) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* eliminates duplicate objects in DST.
|
||||||
|
*/
|
||||||
|
class eliminateDuplicatesInDST : public eliminateDuplicatesInRE_cisco
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
eliminateDuplicatesInDST(const std::string &n) :
|
||||||
|
eliminateDuplicatesInRE_cisco(n,libfwbuilder::RuleElementDst::TYPENAME) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* eliminates duplicate objects in SRV
|
||||||
|
*/
|
||||||
|
class eliminateDuplicatesInSRV : public eliminateDuplicatesInRE_cisco
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
eliminateDuplicatesInSRV(const std::string &n) :
|
||||||
|
eliminateDuplicatesInRE_cisco(n,libfwbuilder::RuleElementSrv::TYPENAME) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Placeholders for MultiAddressRunTime objects which are not
|
||||||
|
* supported for Cisco devices (IOS and PIX, at least)
|
||||||
|
*/
|
||||||
|
class processMultiAddressObjectsInRE : public PolicyRuleProcessor
|
||||||
|
{
|
||||||
|
std::string re_type;
|
||||||
|
public:
|
||||||
|
processMultiAddressObjectsInRE(const std::string &name,
|
||||||
|
const std::string &t) : PolicyRuleProcessor(name) { re_type=t; }
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class processMultiAddressObjectsInSrc : public processMultiAddressObjectsInRE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
processMultiAddressObjectsInSrc(const std::string &n) :
|
||||||
|
processMultiAddressObjectsInRE(n,libfwbuilder::RuleElementSrc::TYPENAME) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class processMultiAddressObjectsInDst : public processMultiAddressObjectsInRE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
processMultiAddressObjectsInDst(const std::string &n) :
|
||||||
|
processMultiAddressObjectsInRE(n,libfwbuilder::RuleElementDst::TYPENAME) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
Helper helper;
|
||||||
|
std::map<std::string,ciscoACL*> acls;
|
||||||
|
|
||||||
|
virtual std::string myPlatformName();
|
||||||
|
|
||||||
|
std::string mangleInterfaceName(const std::string &interface_name);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
PolicyCompiler_cisco(libfwbuilder::FWObjectDatabase *_db,
|
||||||
|
const std::string &fwname,
|
||||||
|
fwcompiler::OSConfigurator *_oscnf);
|
||||||
|
virtual ~PolicyCompiler_cisco() {}
|
||||||
|
|
||||||
|
virtual std::string createRuleLabel(const std::string &txt,
|
||||||
|
libfwbuilder::Interface *iface,
|
||||||
|
int rule_num);
|
||||||
|
|
||||||
|
virtual int prolog();
|
||||||
|
virtual void compile();
|
||||||
|
virtual void epilog();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sort commands ('icmp', 'telnet', 'ssh') and access lists
|
||||||
|
* in some kind of 'natural' order. Useful for both IOS and PIX
|
||||||
|
*/
|
||||||
|
void regroup();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,320 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2002 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: PolicyCompiler_cisco_acls.cpp,v 1.1 2008/03/06 06:48:57 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 "config.h"
|
||||||
|
|
||||||
|
#include "PolicyCompiler_cisco.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 <map>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
|
using namespace libfwbuilder;
|
||||||
|
using namespace fwcompiler;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
bool PolicyCompiler_cisco::setInterfaceAndDirectionBySrc::processNext()
|
||||||
|
{
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
Helper helper(compiler);
|
||||||
|
|
||||||
|
RuleElementItf *itfre=rule->getItf();
|
||||||
|
RuleElementSrc *srcre=rule->getSrc();
|
||||||
|
|
||||||
|
list<string> intf_id_list;
|
||||||
|
|
||||||
|
if (rule->getInterfaceId().empty())
|
||||||
|
{
|
||||||
|
if (rule->getDirection()==PolicyRule::Both)
|
||||||
|
intf_id_list = helper.findInterfaceByNetzoneOrAll( srcre );
|
||||||
|
|
||||||
|
if (rule->getDirection()==PolicyRule::Inbound)
|
||||||
|
intf_id_list = helper.getAllInterfaceIDs();
|
||||||
|
|
||||||
|
for (list<string>::iterator i = intf_id_list.begin(); i!=intf_id_list.end(); ++i)
|
||||||
|
{
|
||||||
|
string intf_id = *i;
|
||||||
|
Interface *ifs = Interface::cast(
|
||||||
|
rule->getRoot()->findInIndex(intf_id) );
|
||||||
|
assert(ifs);
|
||||||
|
if (ifs->isUnprotected()) continue; // skip!
|
||||||
|
|
||||||
|
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);
|
||||||
|
new_rule->setDirection(PolicyRule::Inbound);
|
||||||
|
new_rule->setBool("interface_and_direction_set_from_src",true);
|
||||||
|
tmp_queue.push_back(new_rule);
|
||||||
|
}
|
||||||
|
// preserve original rule as well to let
|
||||||
|
// setInterfaceAndDirectionByDst work on it.
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyCompiler_cisco::setInterfaceAndDirectionByDst::processNext()
|
||||||
|
{
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
Helper helper(compiler);
|
||||||
|
|
||||||
|
if (rule->getBool("interface_and_direction_set_from_src"))
|
||||||
|
{
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
RuleElementItf *itfre=rule->getItf();
|
||||||
|
RuleElementDst *dstre=rule->getDst();
|
||||||
|
|
||||||
|
list<string> intf_id_list;
|
||||||
|
|
||||||
|
if (rule->getInterfaceId().empty())
|
||||||
|
{
|
||||||
|
if (rule->getDirection()==PolicyRule::Both)
|
||||||
|
intf_id_list = helper.findInterfaceByNetzoneOrAll( dstre );
|
||||||
|
|
||||||
|
if (rule->getDirection()==PolicyRule::Outbound)
|
||||||
|
intf_id_list = helper.getAllInterfaceIDs();
|
||||||
|
|
||||||
|
for (list<string>::iterator i = intf_id_list.begin(); i!=intf_id_list.end(); ++i)
|
||||||
|
{
|
||||||
|
string intf_id = *i;
|
||||||
|
Interface *ifs = Interface::cast(
|
||||||
|
rule->getRoot()->findInIndex(intf_id) );
|
||||||
|
assert(ifs);
|
||||||
|
if (ifs->isUnprotected()) continue; // skip!
|
||||||
|
|
||||||
|
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);
|
||||||
|
new_rule->setDirection(PolicyRule::Outbound);
|
||||||
|
new_rule->setBool("interface_and_direction_set_from_dst",true);
|
||||||
|
tmp_queue.push_back(new_rule);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyCompiler_cisco::setInterfaceAndDirectionIfInterfaceSet::processNext()
|
||||||
|
{
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
|
||||||
|
RuleElementItf *itfre=rule->getItf();
|
||||||
|
|
||||||
|
if (rule->getInterfaceId().empty() ||
|
||||||
|
rule->getBool("interface_and_direction_set_from_src") ||
|
||||||
|
rule->getBool("interface_and_direction_set_from_dst"))
|
||||||
|
{
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PolicyRule *new_rule;
|
||||||
|
|
||||||
|
if ( ! rule->getInterfaceId().empty() )
|
||||||
|
{
|
||||||
|
string rule_iface_id = rule->getInterfaceId();
|
||||||
|
|
||||||
|
if (rule->getDirection()==PolicyRule::Both)
|
||||||
|
{
|
||||||
|
new_rule =
|
||||||
|
PolicyRule::cast(compiler->dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
compiler->temp_ruleset->add(new_rule);
|
||||||
|
new_rule->duplicate(rule);
|
||||||
|
new_rule->setInterfaceId( rule_iface_id );
|
||||||
|
new_rule->setDirection(PolicyRule::Inbound);
|
||||||
|
new_rule->setBool("interface_and_direction_set",true);
|
||||||
|
tmp_queue.push_back(new_rule);
|
||||||
|
|
||||||
|
new_rule =
|
||||||
|
PolicyRule::cast(compiler->dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
compiler->temp_ruleset->add(new_rule);
|
||||||
|
new_rule->duplicate(rule);
|
||||||
|
new_rule->setInterfaceId( rule_iface_id );
|
||||||
|
new_rule->setDirection(PolicyRule::Outbound);
|
||||||
|
new_rule->setBool("interface_and_direction_set",true);
|
||||||
|
tmp_queue.push_back(new_rule);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
new_rule =
|
||||||
|
PolicyRule::cast(compiler->dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
compiler->temp_ruleset->add(new_rule);
|
||||||
|
new_rule->duplicate(rule);
|
||||||
|
new_rule->setInterfaceId( rule_iface_id );
|
||||||
|
// direction is copied from the original rule
|
||||||
|
new_rule->setBool("interface_and_direction_set",true);
|
||||||
|
tmp_queue.push_back(new_rule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyCompiler_cisco::pickACL::processNext()
|
||||||
|
{
|
||||||
|
PolicyCompiler_cisco *cisco_comp=dynamic_cast<PolicyCompiler_cisco*>(compiler);
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
|
||||||
|
Interface *rule_iface = compiler->getCachedFwInterface(rule->getInterfaceId());
|
||||||
|
if(rule_iface==NULL)
|
||||||
|
{
|
||||||
|
compiler->abort("Missing interface assignment for rule "+rule->getLabel());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* option 'Generate outbound access lists' is called
|
||||||
|
* 'pix_generate_out_acl' for PIX and 'generate_out_acl' for
|
||||||
|
* IOS. Need to check the right one depending on what platform
|
||||||
|
* this compiler is for. Class PolicyCompiler_cisco is base class
|
||||||
|
* and can be used for both.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool generate_out_acl = false;
|
||||||
|
|
||||||
|
if (compiler->myPlatformName()=="pix")
|
||||||
|
generate_out_acl = compiler->fw->getOptionsObject()->
|
||||||
|
getBool("pix_generate_out_acl");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (compiler->myPlatformName()=="iosacl")
|
||||||
|
generate_out_acl = true;
|
||||||
|
else
|
||||||
|
generate_out_acl = compiler->fw->getOptionsObject()->
|
||||||
|
getBool("generate_out_acl");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule->getDirection() == PolicyRule::Outbound && !generate_out_acl)
|
||||||
|
compiler->abort("Rule with direction 'Outbound' requires outbound ACL but option 'Generate outbound access lists' is OFF. Rule " + rule->getLabel());
|
||||||
|
|
||||||
|
/* The choice of the ACL name depends on whether this is a named
|
||||||
|
* acl or not. If not, should use unique numbers. Also need to
|
||||||
|
* pass this flag to the ciscoACL object.
|
||||||
|
*/
|
||||||
|
string acl_name = rule_iface->getLabel();
|
||||||
|
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"; }
|
||||||
|
rule->setStr("acl",acl_name);
|
||||||
|
|
||||||
|
ciscoACL *acl = new ciscoACL(acl_name, rule_iface, dir, using_named_acl);
|
||||||
|
cisco_comp->acls[acl_name] = acl;
|
||||||
|
|
||||||
|
acl->setWorkName(acl_name);
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Take interface name as an argument and produce
|
||||||
|
* shortened, space-free string that uniquely identifies interface
|
||||||
|
* in a human-readable way.
|
||||||
|
*/
|
||||||
|
|
||||||
|
std::string PolicyCompiler_cisco::mangleInterfaceName(const string &interface_name)
|
||||||
|
{
|
||||||
|
string::size_type n;
|
||||||
|
string s = interface_name;
|
||||||
|
|
||||||
|
// lowercase all characters
|
||||||
|
transform (s.begin(), s.end(), // source
|
||||||
|
s.begin(), // destination
|
||||||
|
::tolower); // operation
|
||||||
|
|
||||||
|
map<string,string> name_mapping;
|
||||||
|
map<string,string>::iterator nmi;
|
||||||
|
|
||||||
|
name_mapping["async"] = "as";
|
||||||
|
name_mapping["atm"] = "atm";
|
||||||
|
name_mapping["bri"] = "bri";
|
||||||
|
name_mapping["ethernet"] = "e";
|
||||||
|
name_mapping["fastethernet"] = "fe";
|
||||||
|
name_mapping["fddi"] = "fddi";
|
||||||
|
name_mapping["gigabitethernet"] = "ge";
|
||||||
|
name_mapping["hssi"] = "h";
|
||||||
|
name_mapping["loopback"] = "l";
|
||||||
|
name_mapping["port-channel"] = "pc";
|
||||||
|
name_mapping["pos"] = "pos";
|
||||||
|
name_mapping["serial"] = "s";
|
||||||
|
name_mapping["switch"] = "sw";
|
||||||
|
name_mapping["tokenring"] = "tr";
|
||||||
|
name_mapping["tunnel"] = "tun";
|
||||||
|
name_mapping["tengigabitethernet"] = "te";
|
||||||
|
name_mapping["sonet"] = "so";
|
||||||
|
name_mapping["vg-anylan"] = "vg";
|
||||||
|
|
||||||
|
for (nmi=name_mapping.begin(); nmi!=name_mapping.end(); nmi++)
|
||||||
|
{
|
||||||
|
if (s.find( nmi->first )==0)
|
||||||
|
{
|
||||||
|
s.replace(0, nmi->first.size(), nmi->second);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( (n=s.find(" "))!=string::npos)
|
||||||
|
{
|
||||||
|
s.replace(n,1,"_");
|
||||||
|
}
|
||||||
|
while ( (n=s.find("/"))!=string::npos)
|
||||||
|
{
|
||||||
|
s.replace(n,1,"_");
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#-*- mode: makefile; tab-width: 4; -*-
|
||||||
|
#
|
||||||
|
include(../../qmake.inc)
|
||||||
|
#
|
||||||
|
TEMPLATE = lib
|
||||||
|
#
|
||||||
|
SOURCES = PolicyCompiler_cisco.cpp \
|
||||||
|
PolicyCompiler_cisco_acls.cpp \
|
||||||
|
ACL.cpp \
|
||||||
|
Helper.cpp
|
||||||
|
|
||||||
|
HEADERS = ../../config.h \
|
||||||
|
ACL.h \
|
||||||
|
Helper.h \
|
||||||
|
PolicyCompiler_cisco.h
|
||||||
|
|
||||||
|
!macx:LIBS += $$LIBS_FWCOMPILER
|
||||||
|
# macx:LIBS += -L../../../libfwbuilder2-2.0.0/src/fwcompiler -lfwcompiler-2.0
|
||||||
|
|
||||||
|
CONFIG += staticlib
|
||||||
|
|
||||||
|
TARGET = fwbcisco
|
||||||
|
|
||||||
|
INSTALLS -= target
|
||||||
@@ -117,12 +117,6 @@ void init(char * const *argv)
|
|||||||
if (n0!=string::npos) appRootDir=argv0.substr(0,n0) + FS_SEPARATOR;
|
if (n0!=string::npos) appRootDir=argv0.substr(0,n0) + FS_SEPARATOR;
|
||||||
else appRootDir="";
|
else appRootDir="";
|
||||||
|
|
||||||
if (fwbdebug)
|
|
||||||
{
|
|
||||||
qDebug(QString("argv0=%1").arg(argv0.c_str()).toAscii().constData());
|
|
||||||
qDebug(QString("appRootDir=%1").arg(appRootDir.c_str()).toAscii().constData());
|
|
||||||
}
|
|
||||||
|
|
||||||
libfwbuilder::init();
|
libfwbuilder::init();
|
||||||
|
|
||||||
#if defined(Q_OS_WIN32) || defined(Q_OS_MACX)
|
#if defined(Q_OS_WIN32) || defined(Q_OS_MACX)
|
||||||
|
|||||||
@@ -0,0 +1,230 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2007 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: OSConfigurator_ios.cpp,v 1.1 2008/03/06 06:48:57 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 "OSConfigurator_ios.h"
|
||||||
|
#include "Helper.h"
|
||||||
|
#include "fwbuilder/Resources.h"
|
||||||
|
|
||||||
|
#include "fwbuilder/Firewall.h"
|
||||||
|
#include "fwbuilder/FWOptions.h"
|
||||||
|
#include "fwbuilder/Interface.h"
|
||||||
|
#include "fwbuilder/Management.h"
|
||||||
|
#include "fwbuilder/Resources.h"
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace libfwbuilder;
|
||||||
|
using namespace fwcompiler;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
string OSConfigurator_ios::myPlatformName() { return "ios"; }
|
||||||
|
|
||||||
|
int OSConfigurator_ios::prolog()
|
||||||
|
{
|
||||||
|
string host_os = fw->getStr("host_OS");
|
||||||
|
|
||||||
|
if (host_os!="ios")
|
||||||
|
abort("Unsupported OS " + host_os );
|
||||||
|
|
||||||
|
return Compiler::prolog();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OSConfigurator_ios::processFirewallOptions()
|
||||||
|
{
|
||||||
|
// FWOptions* options=fw->getOptionsObject();
|
||||||
|
string s;
|
||||||
|
// int i;
|
||||||
|
string version = fw->getStr("version");
|
||||||
|
string platform = fw->getStr("platform");
|
||||||
|
|
||||||
|
|
||||||
|
if ( fw->getOptionsObject()->getBool("ios_set_host_name") )
|
||||||
|
{
|
||||||
|
output << "hostname " << fw->getName() << endl;
|
||||||
|
output << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
output << _printNameif();
|
||||||
|
output << endl;
|
||||||
|
output << _printIPAddress();
|
||||||
|
output << endl;
|
||||||
|
output << _printLogging();
|
||||||
|
output << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
string OSConfigurator_ios::_printNameif()
|
||||||
|
{
|
||||||
|
ostringstream res;
|
||||||
|
string version = fw->getStr("version");
|
||||||
|
string platform = fw->getStr("platform");
|
||||||
|
string::size_type n;
|
||||||
|
|
||||||
|
list<FWObject*> l2=fw->getByType(Interface::TYPENAME);
|
||||||
|
for (list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i)
|
||||||
|
{
|
||||||
|
Interface *iface=dynamic_cast<Interface*>(*i);
|
||||||
|
assert(iface);
|
||||||
|
|
||||||
|
string nameifCmd = Resources::platform_res[platform]->getResourceStr(
|
||||||
|
string("/FWBuilderResources/Target/options/version_")+
|
||||||
|
version+"/ios_commands/nameif");
|
||||||
|
|
||||||
|
if ((n = nameifCmd.find("%il"))!=string::npos)
|
||||||
|
nameifCmd.replace(n,3,iface->getLabel());
|
||||||
|
if ((n = nameifCmd.find("%in"))!=string::npos)
|
||||||
|
nameifCmd.replace(n,3,iface->getName());
|
||||||
|
res << nameifCmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
res << endl;
|
||||||
|
|
||||||
|
return res.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
string OSConfigurator_ios::_printIPAddress()
|
||||||
|
{
|
||||||
|
ostringstream res;
|
||||||
|
string version = fw->getStr("version");
|
||||||
|
string platform = fw->getStr("platform");
|
||||||
|
string setAddrCmd;
|
||||||
|
string::size_type n;
|
||||||
|
|
||||||
|
if ( fw->getOptionsObject()->getBool("ios_ip_address") )
|
||||||
|
{
|
||||||
|
list<FWObject*> l2=fw->getByType(Interface::TYPENAME);
|
||||||
|
for (list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i)
|
||||||
|
{
|
||||||
|
Interface *iface=dynamic_cast<Interface*>(*i);
|
||||||
|
assert(iface);
|
||||||
|
if (iface->isDyn())
|
||||||
|
{
|
||||||
|
setAddrCmd = Resources::platform_res[platform]->getResourceStr(
|
||||||
|
string("/FWBuilderResources/Target/options/version_")+
|
||||||
|
version+"/ios_commands/ip_addr_dyn");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (iface->isUnnumbered())
|
||||||
|
{
|
||||||
|
setAddrCmd = "";
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
setAddrCmd = Resources::platform_res[platform]->getResourceStr(
|
||||||
|
string("/FWBuilderResources/Target/options/version_")+
|
||||||
|
version+"/ios_commands/ip_addr_static");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((n = setAddrCmd.find("%il"))!=string::npos)
|
||||||
|
setAddrCmd.replace(n,3,iface->getLabel());
|
||||||
|
if ((n = setAddrCmd.find("%in"))!=string::npos)
|
||||||
|
setAddrCmd.replace(n,3,iface->getName());
|
||||||
|
if ((n = setAddrCmd.find("%a"))!=string::npos)
|
||||||
|
setAddrCmd.replace(n,2,iface->getAddress().toString());
|
||||||
|
if ((n = setAddrCmd.find("%n"))!=string::npos)
|
||||||
|
setAddrCmd.replace(n,2,iface->getNetmask().toString());
|
||||||
|
|
||||||
|
res << setAddrCmd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res << endl;
|
||||||
|
|
||||||
|
return res.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string OSConfigurator_ios::_printLogging()
|
||||||
|
{
|
||||||
|
Helper helper(this);
|
||||||
|
|
||||||
|
ostringstream str;
|
||||||
|
bool logging_on=false;
|
||||||
|
|
||||||
|
string syslog_host = fw->getOptionsObject()->getStr("ios_syslog_host");
|
||||||
|
string syslog_facility= fw->getOptionsObject()->getStr("ios_syslog_facility");
|
||||||
|
string trap_level= fw->getOptionsObject()->getStr("ios_logging_trap_level");
|
||||||
|
|
||||||
|
bool buffered= fw->getOptionsObject()->getBool("ios_logging_buffered");
|
||||||
|
string buffered_level= fw->getOptionsObject()->getStr("ios_logging_buffered_level");
|
||||||
|
|
||||||
|
bool console= fw->getOptionsObject()->getBool("ios_logging_console");
|
||||||
|
string console_level= fw->getOptionsObject()->getStr("ios_logging_console_level");
|
||||||
|
|
||||||
|
bool timestamp= fw->getOptionsObject()->getBool("ios_logging_timestamp");
|
||||||
|
|
||||||
|
if ( ! timestamp ) str << "no ";
|
||||||
|
str << "service timestamp log datetime localtime" << endl;
|
||||||
|
|
||||||
|
if ( ! syslog_host.empty() )
|
||||||
|
{
|
||||||
|
str << endl;
|
||||||
|
|
||||||
|
str << "logging host " << syslog_host << endl;
|
||||||
|
|
||||||
|
if ( ! syslog_facility.empty() )
|
||||||
|
str << "logging facility " << syslog_facility << endl;
|
||||||
|
|
||||||
|
if ( ! trap_level.empty() )
|
||||||
|
str << "logging trap " << trap_level << endl;
|
||||||
|
|
||||||
|
logging_on=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! buffered ) str << "no logging buffered" << endl;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
str << "logging buffered " << buffered_level << endl;
|
||||||
|
logging_on=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! console ) str << "no logging console" << endl;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
str << "logging console " << console_level << endl;
|
||||||
|
logging_on=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
str << endl;
|
||||||
|
|
||||||
|
return str.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSConfigurator_ios::addVirtualAddressForNAT(const Address *addr)
|
||||||
|
{
|
||||||
|
if (addr==NULL) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSConfigurator_ios::addVirtualAddressForNAT(const Network *nw)
|
||||||
|
{
|
||||||
|
if (nw==NULL) ;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2007 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: OSConfigurator_ios.h,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
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _OSNETWORKCONFIGURATOR_IOS_HH
|
||||||
|
#define _OSNETWORKCONFIGURATOR_IOS_HH
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "fwcompiler/OSConfigurator.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace fwcompiler {
|
||||||
|
|
||||||
|
class OSConfigurator_ios : public OSConfigurator {
|
||||||
|
|
||||||
|
std::string _printNameif();
|
||||||
|
std::string _printIPAddress();
|
||||||
|
std::string _printLogging();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~OSConfigurator_ios() {};
|
||||||
|
OSConfigurator_ios(libfwbuilder::FWObjectDatabase *_db,const std::string &fwname) :
|
||||||
|
OSConfigurator(_db,fwname) {}
|
||||||
|
|
||||||
|
virtual int prolog();
|
||||||
|
|
||||||
|
virtual std::string myPlatformName();
|
||||||
|
virtual void processFirewallOptions();
|
||||||
|
virtual void addVirtualAddressForNAT(const libfwbuilder::Address *addr);
|
||||||
|
virtual void addVirtualAddressForNAT(const libfwbuilder::Network *nw);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,404 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2007 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: PolicyCompiler_iosacl.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 "config.h"
|
||||||
|
|
||||||
|
#include "PolicyCompiler_iosacl.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;
|
||||||
|
|
||||||
|
string PolicyCompiler_iosacl::myPlatformName() { return "iosacl"; }
|
||||||
|
|
||||||
|
PolicyCompiler_iosacl::PolicyCompiler_iosacl(FWObjectDatabase *_db,
|
||||||
|
const std::string &fwname,
|
||||||
|
OSConfigurator *_oscnf) :
|
||||||
|
PolicyCompiler_cisco(_db,fwname,_oscnf)
|
||||||
|
{
|
||||||
|
resetinbound=false;
|
||||||
|
fragguard=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PolicyCompiler_iosacl::prolog()
|
||||||
|
{
|
||||||
|
string version = fw->getStr("version");
|
||||||
|
string platform = fw->getStr("platform");
|
||||||
|
string host_os = fw->getStr("host_OS");
|
||||||
|
|
||||||
|
if (platform!="iosacl")
|
||||||
|
abort("Unsupported platform " + platform );
|
||||||
|
|
||||||
|
object_groups = new Group();
|
||||||
|
dbcopy->add( object_groups );
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
string::size_type slash_idx = temp_acl_addr.find('/');
|
||||||
|
string addr = temp_acl_addr;
|
||||||
|
string netmask = "255.255.255.255";
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
Netmask nm(netmask);
|
||||||
|
nm.to32BitInt(); // to avoid warning abt unused var
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
int nm_length;
|
||||||
|
istringstream str(netmask);
|
||||||
|
str >> nm_length;
|
||||||
|
Netmask nm(nm_length);
|
||||||
|
netmask = nm.toString();
|
||||||
|
}
|
||||||
|
} catch(FWException &ex)
|
||||||
|
{
|
||||||
|
abort("Invalid netmask for management subnet: '"+netmask+"'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IPAddress a(addr);
|
||||||
|
a.to32BitInt();
|
||||||
|
} catch(FWException &ex)
|
||||||
|
{
|
||||||
|
abort("Invalid address for management subnet: '"+addr+"'");
|
||||||
|
}
|
||||||
|
|
||||||
|
string clearACLcmd = Resources::platform_res[platform]->getResourceStr(
|
||||||
|
string("/FWBuilderResources/Target/options/")+
|
||||||
|
"version_"+version+"/iosacl_commands/clear_ip_acl");
|
||||||
|
|
||||||
|
output << endl;
|
||||||
|
|
||||||
|
|
||||||
|
// cisco uses "wildcards" instead of netmasks
|
||||||
|
|
||||||
|
long nm = Netmask(netmask).to32BitInt();
|
||||||
|
struct in_addr na;
|
||||||
|
na.s_addr = ~nm;
|
||||||
|
IPAddress nnm(&na);
|
||||||
|
|
||||||
|
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<FWObject*> 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 ip access-group in" << endl;
|
||||||
|
output << " no ip access-group out" << endl;
|
||||||
|
output << " ip access-group " << 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyCompiler_iosacl::checkForDynamicInterface::findDynamicInterface(
|
||||||
|
PolicyRule *rule, RuleElement *rel)
|
||||||
|
{
|
||||||
|
string vers=compiler->fw->getStr("version");
|
||||||
|
for (list<FWObject*>::iterator i1=rel->begin(); i1!=rel->end(); ++i1)
|
||||||
|
{
|
||||||
|
FWObject *o = *i1;
|
||||||
|
FWObject *obj = NULL;
|
||||||
|
if (FWReference::cast(o)!=NULL) obj=FWReference::cast(o)->getPointer();
|
||||||
|
Interface *iface=Interface::cast(obj);
|
||||||
|
if (iface!=NULL && iface->isDyn())
|
||||||
|
compiler->abort("Dynamic interface can not be used in the IOS ACL rules. Rule "+rule->getLabel());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyCompiler_iosacl::checkForDynamicInterface::processNext()
|
||||||
|
{
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
|
||||||
|
findDynamicInterface(rule,rule->getSrc());
|
||||||
|
findDynamicInterface(rule,rule->getDst());
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyCompiler_iosacl::SpecialServices::processNext()
|
||||||
|
{
|
||||||
|
PolicyCompiler_iosacl *iosacl_comp=dynamic_cast<PolicyCompiler_iosacl*>(compiler);
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
Service *s=compiler->getFirstSrv(rule);
|
||||||
|
|
||||||
|
if (IPService::cast(s)!=NULL)
|
||||||
|
{
|
||||||
|
if (s->getBool("rr") ||
|
||||||
|
s->getBool("ssrr") ||
|
||||||
|
s->getBool("ts") )
|
||||||
|
compiler->abort("IOS ACL does not support checking for IP options in ACLs. Rule: "+rule->getLabel());
|
||||||
|
}
|
||||||
|
if (TCPService::cast(s)!=NULL) {
|
||||||
|
if (s->getBool("ack_flag") ||
|
||||||
|
s->getBool("fin_flag") ||
|
||||||
|
s->getBool("rst_flag") ||
|
||||||
|
s->getBool("syn_flag") )
|
||||||
|
compiler->abort("IOS ACL does not support checking for TCP options in ACLs. Rule: "+rule->getLabel());
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolicyCompiler_iosacl::compile()
|
||||||
|
{
|
||||||
|
cout << " Compiling policy for " << fw->getName() << " ..." << endl << flush;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string vers = fw->getStr("version");
|
||||||
|
string platform = fw->getStr("platform");
|
||||||
|
|
||||||
|
Compiler::compile();
|
||||||
|
|
||||||
|
addDefaultPolicyRule();
|
||||||
|
|
||||||
|
if ( fw->getOptionsObject()->getBool ("check_shading") )
|
||||||
|
{
|
||||||
|
add( new Begin ("Detecting rule shadowing" ) );
|
||||||
|
add( new printTotalNumberOfRules ( ) );
|
||||||
|
|
||||||
|
add( new ItfNegation( "process negation in Itf" ) );
|
||||||
|
add( new InterfacePolicyRules(
|
||||||
|
"process interface policy rules and store interface ids"));
|
||||||
|
|
||||||
|
add( new recursiveGroupsInSrc("check for recursive groups in SRC"));
|
||||||
|
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 eliminateDuplicatesInSRC("eliminate duplicates in SRC"));
|
||||||
|
add( new eliminateDuplicatesInDST("eliminate duplicates in DST"));
|
||||||
|
add( new eliminateDuplicatesInSRV("eliminate duplicates in SRV"));
|
||||||
|
add( new ExpandMultipleAddressesInSRC(
|
||||||
|
"expand objects with multiple addresses in SRC" ) );
|
||||||
|
add( new ExpandMultipleAddressesInDST(
|
||||||
|
"expand objects with multiple addresses in DST" ) );
|
||||||
|
add( new ConvertToAtomic("convert to atomic rules" ) );
|
||||||
|
add( new DetectShadowing("Detect shadowing" ) );
|
||||||
|
add( new simplePrintProgress() );
|
||||||
|
|
||||||
|
runRuleProcessors();
|
||||||
|
deleteRuleProcessors();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
add( new Begin (" Start processing rules" ) );
|
||||||
|
add( new printTotalNumberOfRules ( ) );
|
||||||
|
|
||||||
|
add( new recursiveGroupsInSrc( "check for recursive groups in SRC" ) );
|
||||||
|
add( new recursiveGroupsInDst( "check for recursive groups in DST" ) );
|
||||||
|
add( new recursiveGroupsInSrv( "check for recursive groups in SRV" ) );
|
||||||
|
|
||||||
|
add( new emptyGroupsInSrc( "check for empty groups in SRC" ) );
|
||||||
|
add( new emptyGroupsInDst( "check for empty groups in DST" ) );
|
||||||
|
add( new emptyGroupsInSrv( "check for empty groups in SRV" ) );
|
||||||
|
|
||||||
|
add( new ExpandGroups ("expand groups" ) );
|
||||||
|
add( new eliminateDuplicatesInSRC( "eliminate duplicates in SRC" ) );
|
||||||
|
add( new eliminateDuplicatesInDST( "eliminate duplicates in DST" ) );
|
||||||
|
add( new eliminateDuplicatesInSRV( "eliminate duplicates in SRV" ) );
|
||||||
|
|
||||||
|
add( new processMultiAddressObjectsInSrc(
|
||||||
|
"process MultiAddress objects in Src") );
|
||||||
|
add( new processMultiAddressObjectsInDst(
|
||||||
|
"process MultiAddress objects in Dst") );
|
||||||
|
|
||||||
|
add( new ItfNegation( "process negation in Itf" ) );
|
||||||
|
add( new InterfacePolicyRules(
|
||||||
|
"process interface policy rules and store interface ids") );
|
||||||
|
|
||||||
|
add( new splitServices ("split rules with different protocols" ) );
|
||||||
|
|
||||||
|
add( new ExpandMultipleAddressesInSRC(
|
||||||
|
"expand objects with multiple addresses in SRC" ) );
|
||||||
|
add( new MACFiltering ("check for MAC address filtering" ) );
|
||||||
|
// add( new splitByNetworkZonesForSrc ("split rule if objects in Src belong to different network zones " ) );
|
||||||
|
// add( new replaceFWinDSTPolicy ("replace fw with its interface in DST in global policy rules") );
|
||||||
|
|
||||||
|
add( new ExpandMultipleAddressesInDST(
|
||||||
|
"expand objects with multiple addresses in DST" ) );
|
||||||
|
add( new MACFiltering(
|
||||||
|
"check for MAC address filtering" ) );
|
||||||
|
// 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 setInterfaceAndDirectionBySrc(
|
||||||
|
"Set interface and direction for rules with interface 'all' using SRC"));
|
||||||
|
add( new setInterfaceAndDirectionByDst(
|
||||||
|
"Set interface and direction for rules with interface 'all' using DST"));
|
||||||
|
add( new setInterfaceAndDirectionIfInterfaceSet(
|
||||||
|
"Set direction for rules with interface not 'all'"));
|
||||||
|
|
||||||
|
add( new specialCaseWithDynInterface(
|
||||||
|
"check for a special cases with dynamic interface" ) );
|
||||||
|
|
||||||
|
// first arg is true because we use "ip access-list" for IOS.
|
||||||
|
add( new pickACL( true, "assign ACLs" ) );
|
||||||
|
|
||||||
|
add( new SpecialServices( "check for special services" ) );
|
||||||
|
add( new checkForZeroAddr( "check for zero addresses" ) );
|
||||||
|
add( new checkForDynamicInterface("check for dynamic interfaces" ) );
|
||||||
|
|
||||||
|
/* remove redundant objects only after all splits has been
|
||||||
|
* done, right before object groups are created
|
||||||
|
*/
|
||||||
|
add( new removeRedundantAddressesFromSrc(
|
||||||
|
"remove redundant addresses from Src") );
|
||||||
|
add( new removeRedundantAddressesFromDst(
|
||||||
|
"remove redundant addresses from Dst") );
|
||||||
|
|
||||||
|
add( new ConvertToAtomic ("convert to atomic rules" ) );
|
||||||
|
|
||||||
|
add( new simplePrintProgress());
|
||||||
|
|
||||||
|
add( new createNewCompilerPass ("Creating ACLs ..."));
|
||||||
|
|
||||||
|
// add( new ClearACLs("Clear ACLs"));
|
||||||
|
|
||||||
|
// This processor prints each ACL separately in one block.
|
||||||
|
// It adds comments inside to denote original rules.
|
||||||
|
//
|
||||||
|
add( new PrintCompleteACLs("Print ACLs"));
|
||||||
|
|
||||||
|
// add( new PrintRule("generate code for ACLs"));
|
||||||
|
add( new simplePrintProgress());
|
||||||
|
|
||||||
|
runRuleProcessors();
|
||||||
|
|
||||||
|
} catch (FWException &ex) {
|
||||||
|
error(ex.toString());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string PolicyCompiler_iosacl::printAccessGroupCmd(ciscoACL *acl)
|
||||||
|
{
|
||||||
|
ostringstream str;
|
||||||
|
string dir;
|
||||||
|
if (acl->direction()=="in" || acl->direction()=="Inbound") dir="in";
|
||||||
|
if (acl->direction()=="out" || acl->direction()=="Outbound") dir="out";
|
||||||
|
|
||||||
|
str << "interface " << acl->getInterface()->getName() << endl;
|
||||||
|
str << " ip access-group " << acl->workName() << " " << dir << endl;
|
||||||
|
str << "exit" << endl;
|
||||||
|
return str.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolicyCompiler_iosacl::epilog()
|
||||||
|
{
|
||||||
|
output << endl;
|
||||||
|
|
||||||
|
for (map<string,ciscoACL*>::iterator i=acls.begin(); i!=acls.end(); ++i)
|
||||||
|
{
|
||||||
|
ciscoACL *acl=(*i).second;
|
||||||
|
if (acl->size()!=0) output << printAccessGroupCmd(acl);
|
||||||
|
}
|
||||||
|
output << endl;
|
||||||
|
|
||||||
|
if ( fw->getOptionsObject()->getBool("iosacl_regroup_commands") )
|
||||||
|
{
|
||||||
|
cout << " Regrouping commands \n" << flush;
|
||||||
|
regroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,267 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2007 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: PolicyCompiler_iosacl.h,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
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __POLICYCOMPILER_IOSACL_HH
|
||||||
|
#define __POLICYCOMPILER_IOSACL_HH
|
||||||
|
|
||||||
|
#include <fwbuilder/libfwbuilder-config.h>
|
||||||
|
|
||||||
|
#include "fwcompiler/PolicyCompiler.h"
|
||||||
|
#include "fwbuilder/RuleElement.h"
|
||||||
|
|
||||||
|
#include "Helper.h"
|
||||||
|
#include "ACL.h"
|
||||||
|
#include "PolicyCompiler_cisco.h"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace libfwbuilder {
|
||||||
|
class IPService;
|
||||||
|
class ICMPService;
|
||||||
|
class TCPService;
|
||||||
|
class UDPService;
|
||||||
|
class RuleElementSrc;
|
||||||
|
class RuleElementDst;
|
||||||
|
class RuleElementSrv;
|
||||||
|
class Group;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace fwcompiler {
|
||||||
|
|
||||||
|
class PolicyCompiler_iosacl : public PolicyCompiler_cisco {
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dynamic interfaces can not be used in policy rules in IOS ACLs
|
||||||
|
*/
|
||||||
|
friend class checkForDynamicInterface;
|
||||||
|
class checkForDynamicInterface : public PolicyRuleProcessor
|
||||||
|
{
|
||||||
|
bool findDynamicInterface(libfwbuilder::PolicyRule *rule,
|
||||||
|
libfwbuilder::RuleElement *re);
|
||||||
|
public:
|
||||||
|
checkForDynamicInterface(const std::string &name) : PolicyRuleProcessor(name) {}
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*************************************************************************
|
||||||
|
*
|
||||||
|
* the following rule processors are intended for IOSACL < 7.0
|
||||||
|
* the code is in the module PolicyCompiler_iosacl_v6_acls.cpp
|
||||||
|
*
|
||||||
|
*************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* verifies combination of interface and direction and
|
||||||
|
* fills interface and direction. After this predicate it
|
||||||
|
* is guaranteed that both interface and direction have
|
||||||
|
* some value. In certain situations interface ID may be
|
||||||
|
* set to "nil" though (e.g. global policy rules).
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( InterfaceAndDirection_v6 );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if interface has not been defined (this is global policy
|
||||||
|
* rule), then multiply the rule for each interface and set
|
||||||
|
* direction to "Inbound"
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( assignRuleToInterface_v6 );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* split rules with direction "both".
|
||||||
|
* TODO: This is used in OpenBSD pf. Move to class PolicyCompiler
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( SplitDirection_v6 );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* in IOSACL, ACLs are always applied on interface and direction
|
||||||
|
* can only be "inbound". We emulate outbound ACLs though.
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( EmulateOutboundACL_v6 );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* determine acl rules should belong to
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( pickACL_v6 );
|
||||||
|
friend class PolicyCompiler_iosacl::pickACL_v6;
|
||||||
|
|
||||||
|
/*
|
||||||
|
*************************************************************************
|
||||||
|
*
|
||||||
|
* end of module PolicyCompiler_iosacl_v6_acls.cpp
|
||||||
|
*
|
||||||
|
*************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
*************************************************************************
|
||||||
|
*
|
||||||
|
* rule processors intended to manage ACLs for IOSACL < 7.0 are inherited
|
||||||
|
* from PolicyCompiler_cisco.
|
||||||
|
* The code is in the module PolicyCompiler_cisco_acls.cpp
|
||||||
|
*
|
||||||
|
* The processors assume that all objects in src and dst
|
||||||
|
* belong to the same network zone (respectively)
|
||||||
|
*
|
||||||
|
* All these rule processors assume outbound ACLs are supported.
|
||||||
|
* Check corresponding capability flag and do not include these
|
||||||
|
* processors in the processors chain in iosacl.cpp if outbound acls
|
||||||
|
* are not supported.
|
||||||
|
*
|
||||||
|
*************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this processor checks for the services which require
|
||||||
|
* special treatment. Some of these will be checking for
|
||||||
|
* source or destination object as well because special
|
||||||
|
* command may need to be generated in case source or
|
||||||
|
* destination is a firewall itself. Therefore this processor
|
||||||
|
* should be called after converting to atomic rules, but
|
||||||
|
* before interface addresses in source and destination are
|
||||||
|
* expanded.
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( SpecialServices );
|
||||||
|
friend class PolicyCompiler_iosacl::SpecialServices;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* to implement action "Reject" add command "service resetinbound"
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( RejectAction );
|
||||||
|
friend class PolicyCompiler_iosacl::RejectAction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this processor accumulates all rules fed to it by previous
|
||||||
|
* * processors, prints commands to clear access-lists, then
|
||||||
|
* feeds all rules to the next processor. Usually this
|
||||||
|
* processor is in chain right before PrintRules.
|
||||||
|
*
|
||||||
|
* We use this processor to print "clear" commands because
|
||||||
|
* they need to be generated when all access lists have been
|
||||||
|
* created but before they are printed.
|
||||||
|
*/
|
||||||
|
class ClearACLs : public PolicyRuleProcessor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ClearACLs(const std::string &n) : PolicyRuleProcessor(n) {}
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
friend class PolicyCompiler_iosacl::ClearACLs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this processor prints single policy rule, assuming all
|
||||||
|
* groups have been expanded, so source, destination and
|
||||||
|
* service hold exactly one object each, and this object is
|
||||||
|
* not a group. Negation should also have been taken care of
|
||||||
|
* before this method is called.
|
||||||
|
*/
|
||||||
|
class PrintRule : public PolicyRuleProcessor
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::string current_rule_label1;
|
||||||
|
std::map<std::string,std::string> current_rule_label2;
|
||||||
|
int aclLineCounter;
|
||||||
|
|
||||||
|
std::string _printSrcService(libfwbuilder::Service *srv);
|
||||||
|
std::string _printDstService(libfwbuilder::Service *srv);
|
||||||
|
std::string _printAddr(libfwbuilder::Address *o);
|
||||||
|
std::string _printAction(libfwbuilder::PolicyRule *r);
|
||||||
|
std::string _printACL(libfwbuilder::PolicyRule *r);
|
||||||
|
std::string _printLog(libfwbuilder::PolicyRule *r);
|
||||||
|
std::string _printFragm(libfwbuilder::Service *srv);
|
||||||
|
|
||||||
|
std::string _printRule(libfwbuilder::PolicyRule *rule);
|
||||||
|
|
||||||
|
public:
|
||||||
|
PrintRule(const std::string &name) : PolicyRuleProcessor(name) { aclLineCounter=0; }
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
friend class PolicyCompiler_iosacl::PrintRule;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this processor accumulates all rules fed to it by previous
|
||||||
|
* * processors, prints commands to clear access-lists, then
|
||||||
|
* generates commands for the new ACLs.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class PrintCompleteACLs : public PrintRule
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PrintCompleteACLs(const std::string &n) : PrintRule(n) {}
|
||||||
|
virtual bool processNext();
|
||||||
|
|
||||||
|
struct printRulesForACL : public std::unary_function<libfwbuilder::Rule*, void>
|
||||||
|
{
|
||||||
|
ciscoACL *acl;
|
||||||
|
std::stringstream *output;
|
||||||
|
PolicyCompiler_iosacl *iosacl_comp;
|
||||||
|
PolicyCompiler_iosacl::PrintCompleteACLs *print_acl_p;
|
||||||
|
|
||||||
|
printRulesForACL(PolicyCompiler_iosacl *_comp,
|
||||||
|
PolicyCompiler_iosacl::PrintCompleteACLs *pp,
|
||||||
|
ciscoACL* _acl,
|
||||||
|
std::stringstream *_out)
|
||||||
|
{ iosacl_comp = _comp; print_acl_p = pp; acl = _acl; output = _out; }
|
||||||
|
|
||||||
|
// print rule if it belongs to ACL <acl>
|
||||||
|
void operator() (libfwbuilder::Rule* x);
|
||||||
|
};
|
||||||
|
friend struct PrintCompleteACLs::printRulesForACL;
|
||||||
|
};
|
||||||
|
friend class PolicyCompiler_iosacl::PrintCompleteACLs;;
|
||||||
|
|
||||||
|
|
||||||
|
bool resetinbound;
|
||||||
|
bool fragguard;
|
||||||
|
|
||||||
|
// storage for object groups created to be used with IOSACL command object-group
|
||||||
|
libfwbuilder::Group *object_groups;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual std::string myPlatformName();
|
||||||
|
std::string printAccessGroupCmd(ciscoACL *acl);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
PolicyCompiler_iosacl(libfwbuilder::FWObjectDatabase *_db,
|
||||||
|
const std::string &fwname,
|
||||||
|
fwcompiler::OSConfigurator *_oscnf);
|
||||||
|
virtual ~PolicyCompiler_iosacl() {}
|
||||||
|
|
||||||
|
virtual int prolog();
|
||||||
|
virtual void compile();
|
||||||
|
virtual void epilog();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,434 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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=srv->getInt("src_range_start");
|
||||||
|
int re=srv->getInt("src_range_end");
|
||||||
|
|
||||||
|
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=srv->getInt("dst_range_start");
|
||||||
|
int re=srv->getInt("dst_range_end");
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
ostringstream str;
|
||||||
|
|
||||||
|
IPAddress srcaddr=o->getAddress();
|
||||||
|
Netmask srcmask=o->getNetmask();
|
||||||
|
|
||||||
|
if (Interface::cast(o)!=NULL)
|
||||||
|
{
|
||||||
|
Interface *interface_=Interface::cast(o);
|
||||||
|
if (interface_->isDyn())
|
||||||
|
{
|
||||||
|
return string("interface ") + interface_->getLabel() + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
srcmask=Netmask("255.255.255.255");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IPv4::cast(o)!=NULL)
|
||||||
|
srcmask=Netmask("255.255.255.255");
|
||||||
|
|
||||||
|
|
||||||
|
if (srcaddr.toString()=="0.0.0.0" && srcmask.toString()=="0.0.0.0")
|
||||||
|
{
|
||||||
|
str << "any ";
|
||||||
|
} else {
|
||||||
|
if (srcmask.toString()=="255.255.255.255")
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
IPAddress nnm(&na);
|
||||||
|
|
||||||
|
str << nnm.toString() << " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,429 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2007 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: iosacl.cpp,v 1.2 2008/03/09 05:13:55 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 "config.h"
|
||||||
|
|
||||||
|
#include <qsettings.h>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <map>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# include <direct.h>
|
||||||
|
#else
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "PolicyCompiler_iosacl.h"
|
||||||
|
#include "OSConfigurator_ios.h"
|
||||||
|
|
||||||
|
#include "fwcompiler/Preprocessor.h"
|
||||||
|
|
||||||
|
#include "fwbuilder/Resources.h"
|
||||||
|
#include "fwbuilder/FWObjectDatabase.h"
|
||||||
|
#include "fwbuilder/Firewall.h"
|
||||||
|
#include "fwbuilder/Interface.h"
|
||||||
|
#include "fwbuilder/IPv4.h"
|
||||||
|
#include "fwbuilder/XMLTools.h"
|
||||||
|
#include "fwbuilder/FWException.h"
|
||||||
|
#include "fwbuilder/Tools.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_GETOPT_H
|
||||||
|
#include <getopt.h>
|
||||||
|
#else
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <getopt.h>
|
||||||
|
#else
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../common/init.cpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace libfwbuilder;
|
||||||
|
using namespace fwcompiler;
|
||||||
|
|
||||||
|
|
||||||
|
static const char *filename = NULL;
|
||||||
|
static const char *wdir = NULL;
|
||||||
|
static const char *fwobjectname = NULL;
|
||||||
|
static string ofname = "";
|
||||||
|
static int dl = 0;
|
||||||
|
static int drp = -1;
|
||||||
|
static int drn = -1;
|
||||||
|
static int verbose = 0;
|
||||||
|
static int test_mode = 0;
|
||||||
|
|
||||||
|
FWObjectDatabase *objdb = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
class UpgradePredicate: public XMLTools::UpgradePredicate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual bool operator()(const string &msg) const
|
||||||
|
{
|
||||||
|
msg.size(); // to make compiler happy about unused parameter
|
||||||
|
cout << "Data file has been created in the old version of Firewall Builder.\nLoad it in the GUI to convert it to the new version." << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void usage(const char *name)
|
||||||
|
{
|
||||||
|
cout << "Firewall Builder: policy compiler for Cisco IOS ACL" << endl;
|
||||||
|
cout << "Copyright 2002-2004 NetCitadel, LLC" << endl;
|
||||||
|
cout << "Version " << VERSION << "-" << RELEASE_NUM << endl;
|
||||||
|
cout << "Usage: " << name << " [-tvV] [-f filename.xml] [-d destdir] [-o output.fw] firewall_object_name" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char * const * argv)
|
||||||
|
{
|
||||||
|
if (argc<=1)
|
||||||
|
{
|
||||||
|
usage(argv0.c_str());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int opt;
|
||||||
|
|
||||||
|
while( (opt=getopt(argc,argv,"x:vVf:d:r:tLo:")) != EOF )
|
||||||
|
{
|
||||||
|
switch(opt)
|
||||||
|
{
|
||||||
|
case 'd':
|
||||||
|
wdir = strdup(optarg);
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
respath = string(optarg);
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
filename = strdup(optarg);
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
ofname = string(optarg);
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
if (*optarg=='p') {
|
||||||
|
++optarg;
|
||||||
|
drp = atoi(optarg);
|
||||||
|
} else {
|
||||||
|
if (*optarg=='n') {
|
||||||
|
++optarg;
|
||||||
|
drn = atoi(optarg);
|
||||||
|
} else {
|
||||||
|
if (isdigit(*optarg)) dl=atoi(optarg); // increase debug level
|
||||||
|
else {
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
test_mode++;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
verbose++;
|
||||||
|
break;
|
||||||
|
case 'V':
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(1);
|
||||||
|
case 'h':
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init(argv);
|
||||||
|
|
||||||
|
if((argc-1) != optind)
|
||||||
|
{
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fwobjectname = strdup( argv[optind++] );
|
||||||
|
|
||||||
|
if (ofname.empty())
|
||||||
|
{
|
||||||
|
ofname=string(fwobjectname)+".fw";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filename==NULL || fwobjectname==NULL)
|
||||||
|
{
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wdir==0) wdir="./";
|
||||||
|
|
||||||
|
if (
|
||||||
|
#ifdef _WIN32
|
||||||
|
_chdir(wdir)
|
||||||
|
#else
|
||||||
|
chdir(wdir)
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
|
cerr << "Can't change working directory to: " << wdir << endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (test_mode)
|
||||||
|
cout << "*** Running in test mode, all errors are ignored" << endl << endl;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
new Resources(respath+FS_SEPARATOR+"resources.xml");
|
||||||
|
|
||||||
|
/* create database */
|
||||||
|
objdb = new FWObjectDatabase();
|
||||||
|
|
||||||
|
/* load the data file */
|
||||||
|
UpgradePredicate upgrade_predicate;
|
||||||
|
|
||||||
|
if (verbose) cout << " *** Loading data ...";
|
||||||
|
|
||||||
|
objdb->setReadOnly( false );
|
||||||
|
objdb->load( filename, &upgrade_predicate, librespath);
|
||||||
|
objdb->setFileName(filename);
|
||||||
|
objdb->reIndex();
|
||||||
|
|
||||||
|
if (verbose) cout << " done\n";
|
||||||
|
|
||||||
|
/* why do I do this ?
|
||||||
|
|
||||||
|
FWObject *slib = objdb->findInIndex("syslib000");
|
||||||
|
if ( slib->isReadOnly()) slib->setReadOnly(false);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* some general sanity checks first
|
||||||
|
*/
|
||||||
|
Firewall* fw=objdb->findFirewallByName(fwobjectname);
|
||||||
|
FWOptions* options=fw->getOptionsObject();
|
||||||
|
|
||||||
|
string fwvers = fw->getStr("version");
|
||||||
|
if (fwvers == "") fw->setStr("version", "12.x");
|
||||||
|
|
||||||
|
bool ios_acl_basic=options->getBool("ios_acl_basic");
|
||||||
|
bool ios_acl_no_clear=options->getBool("ios_acl_no_clear");
|
||||||
|
bool ios_acl_substitution=options->getBool("ios_acl_substitution");
|
||||||
|
bool ios_add_clear_statements=options->getBool("ios_add_clear_statements");
|
||||||
|
|
||||||
|
if ( !ios_acl_basic &&
|
||||||
|
!ios_acl_no_clear &&
|
||||||
|
!ios_acl_substitution )
|
||||||
|
{
|
||||||
|
if ( ios_add_clear_statements ) options->setBool("ios_acl_basic",true);
|
||||||
|
else options->setBool("ios_acl_no_clear",true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Helper helper(NULL);
|
||||||
|
|
||||||
|
std::list<FWObject*> l2=fw->getByType(Interface::TYPENAME);
|
||||||
|
for (std::list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i)
|
||||||
|
{
|
||||||
|
Interface *iface=dynamic_cast<Interface*>(*i);
|
||||||
|
assert(iface);
|
||||||
|
|
||||||
|
if ( iface->isDyn())
|
||||||
|
{
|
||||||
|
list<FWObject*> l3=iface->getByType(IPv4::TYPENAME);
|
||||||
|
if (l3.size()>0)
|
||||||
|
{
|
||||||
|
char errstr[256];
|
||||||
|
for (list<FWObject*>::iterator j=l3.begin(); j!=l3.end(); ++j)
|
||||||
|
if ( objdb->findAllReferences(*j).size()!=0 )
|
||||||
|
{
|
||||||
|
sprintf(errstr,
|
||||||
|
_("Dynamic interface %s has an IP address that is used in the firewall policy rule.\n"),
|
||||||
|
iface->getName().c_str() );
|
||||||
|
throw FWException(errstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(errstr,
|
||||||
|
_("Dynamic interface %s should not have an IP address object attached to it. This IP address object will be ignored.\n"),
|
||||||
|
iface->getName().c_str() );
|
||||||
|
cerr << errstr;
|
||||||
|
for (list<FWObject*>::iterator j=l3.begin(); j!=l3.end(); ++j)
|
||||||
|
iface->remove(*j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* no address
|
||||||
|
*/
|
||||||
|
if (iface->isRegular())
|
||||||
|
{
|
||||||
|
FWObject *ipv4=iface->getFirstByType(IPv4::TYPENAME);
|
||||||
|
if (ipv4==NULL)
|
||||||
|
throw FWException(
|
||||||
|
"Interface "+
|
||||||
|
iface->getName()+" ("+iface->getLabel()+") has no address." );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char timestr[256];
|
||||||
|
time_t tm;
|
||||||
|
|
||||||
|
tm=time(NULL);
|
||||||
|
strcpy(timestr,ctime(&tm));
|
||||||
|
timestr[ strlen(timestr)-1 ]='\0';
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
char* user_name=getenv("USERNAME");
|
||||||
|
#else
|
||||||
|
char* user_name=getenv("USER");
|
||||||
|
#endif
|
||||||
|
if (user_name==NULL)
|
||||||
|
throw FWException("Can't figure out your user name, aborting");
|
||||||
|
|
||||||
|
Preprocessor* prep=new Preprocessor(objdb , fwobjectname);
|
||||||
|
prep->compile();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process firewall options, build OS network configuration script
|
||||||
|
*/
|
||||||
|
OSConfigurator *oscnf=NULL;
|
||||||
|
oscnf=new OSConfigurator_ios(objdb , fwobjectname);
|
||||||
|
|
||||||
|
oscnf->prolog();
|
||||||
|
oscnf->processFirewallOptions();
|
||||||
|
|
||||||
|
/* create compilers and run the whole thing */
|
||||||
|
|
||||||
|
PolicyCompiler_iosacl *c = new PolicyCompiler_iosacl(objdb,
|
||||||
|
fwobjectname,
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
ofstream ofile(ofname.c_str(), ios::out|ios::binary);
|
||||||
|
#else
|
||||||
|
ofstream ofile(ofname.c_str());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ofile << "!\n\
|
||||||
|
! This is automatically generated file. DO NOT MODIFY !\n\
|
||||||
|
!\n\
|
||||||
|
! Firewall Builder fwb_iosacl v" << VERSION << "-" << RELEASE_NUM << " \n\
|
||||||
|
!\n\
|
||||||
|
! Generated " << timestr
|
||||||
|
<< " "
|
||||||
|
<< tzname[0]
|
||||||
|
<< " by "
|
||||||
|
<< user_name;
|
||||||
|
|
||||||
|
ofile << endl;
|
||||||
|
|
||||||
|
string vers = fw->getStr("version");
|
||||||
|
string platform = fw->getStr("platform");
|
||||||
|
|
||||||
|
ofile << "!" << endl;
|
||||||
|
ofile << "!" << " Compiled for " << platform << " " << vers << endl;
|
||||||
|
|
||||||
|
ofile << "!" << endl;
|
||||||
|
ofile << "!" << MANIFEST_MARKER << "* " << ofname << endl;
|
||||||
|
ofile << "!" << endl;
|
||||||
|
|
||||||
|
ofile << endl;
|
||||||
|
ofile << "!" << endl;
|
||||||
|
ofile << "! Prolog script:" << endl;
|
||||||
|
ofile << "!" << endl;
|
||||||
|
|
||||||
|
string pre_hook= fw->getOptionsObject()->getStr("ios_prolog_script");
|
||||||
|
ofile << pre_hook << endl;
|
||||||
|
|
||||||
|
ofile << "!" << endl;
|
||||||
|
ofile << "! End of prolog script:" << endl;
|
||||||
|
ofile << "!" << endl;
|
||||||
|
|
||||||
|
|
||||||
|
ofile << oscnf->getCompiledScript();
|
||||||
|
ofile << endl;
|
||||||
|
ofile << c->getCompiledScript();
|
||||||
|
ofile << endl;
|
||||||
|
|
||||||
|
ofile << endl;
|
||||||
|
ofile << "!" << endl;
|
||||||
|
ofile << "! Epilog script:" << endl;
|
||||||
|
ofile << "!" << endl;
|
||||||
|
|
||||||
|
string post_hook= fw->getOptionsObject()->getStr("ios_epilog_script");
|
||||||
|
ofile << post_hook << endl;
|
||||||
|
|
||||||
|
ofile << endl;
|
||||||
|
ofile << "! End of epilog script:" << endl;
|
||||||
|
ofile << "!" << endl;
|
||||||
|
|
||||||
|
ofile.close();
|
||||||
|
|
||||||
|
cout << _(" Compiled successfully") << endl << flush;
|
||||||
|
|
||||||
|
} catch(libfwbuilder::FWException &ex) {
|
||||||
|
cerr << ex.toString() << endl;
|
||||||
|
return 1;
|
||||||
|
} catch (std::string s) {
|
||||||
|
cerr << s << endl;
|
||||||
|
return 1;
|
||||||
|
} catch (std::exception ex) {
|
||||||
|
cerr << "exception: " << ex.what() << endl;
|
||||||
|
return 1;
|
||||||
|
} catch (...) {
|
||||||
|
cerr << "Unsupported exception";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#-*- mode: makefile; tab-width: 4; -*-
|
||||||
|
#
|
||||||
|
include(../../qmake.inc)
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# PACKAGE = fwbuilder-iosacl-$$FWB_VERSION
|
||||||
|
#
|
||||||
|
# QMAKE_CXXFLAGS_DEBUG += -DPACKAGE="\"$$PACKAGE\""
|
||||||
|
# QMAKE_CXXFLAGS_RELEASE += -DPACKAGE="\"$$PACKAGE\""
|
||||||
|
|
||||||
|
SOURCES = OSConfigurator_ios.cpp \
|
||||||
|
iosacl.cpp \
|
||||||
|
PolicyCompiler_iosacl.cpp \
|
||||||
|
PolicyCompiler_iosacl_writers.cpp \
|
||||||
|
|
||||||
|
HEADERS = ../../config.h \
|
||||||
|
OSConfigurator_ios.h \
|
||||||
|
PolicyCompiler_iosacl.h \
|
||||||
|
../cisco_lib/PolicyCompiler_cisco.h \
|
||||||
|
../cisco_lib/ACL.h \
|
||||||
|
../cisco_lib/Helper.h
|
||||||
|
|
||||||
|
# CONFIG -= qt
|
||||||
|
QMAKE_COPY = /usr/bin/install -m 0755 -s
|
||||||
|
|
||||||
|
win32:CONFIG += console
|
||||||
|
|
||||||
|
INCLUDEPATH += ../cisco_lib/
|
||||||
|
|
||||||
|
win32:LIBS += $$PREFIX/fwbcisco.lib
|
||||||
|
!win32:LIBS += ../cisco_lib/libfwbcisco.a
|
||||||
|
|
||||||
|
LIBS += $$LIBS_FWCOMPILER
|
||||||
|
|
||||||
|
TARGET = fwb_iosacl
|
||||||
|
|
||||||
@@ -0,0 +1,1590 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2002 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: NATCompiler_pix.cpp,v 1.1 2008/03/06 06:48:59 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 "config.h"
|
||||||
|
|
||||||
|
#include "NATCompiler_pix.h"
|
||||||
|
|
||||||
|
#include "fwbuilder/FWObjectDatabase.h"
|
||||||
|
#include "fwbuilder/RuleElement.h"
|
||||||
|
#include "fwbuilder/NAT.h"
|
||||||
|
#include "fwbuilder/AddressRange.h"
|
||||||
|
#include "fwbuilder/ICMPService.h"
|
||||||
|
#include "fwbuilder/TCPService.h"
|
||||||
|
#include "fwbuilder/UDPService.h"
|
||||||
|
#include "fwbuilder/Interface.h"
|
||||||
|
#include "fwbuilder/IPv4.h"
|
||||||
|
#include "fwbuilder/IPAddress.h"
|
||||||
|
#include "fwbuilder/Network.h"
|
||||||
|
#include "fwbuilder/Resources.h"
|
||||||
|
#include "fwbuilder/AddressTable.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
using namespace libfwbuilder;
|
||||||
|
using namespace fwcompiler;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
string NATCompiler_pix::myPlatformName() { return "pix"; }
|
||||||
|
|
||||||
|
NATCompiler_pix::NATCompiler_pix(FWObjectDatabase *_db,
|
||||||
|
const std::string &fwname,
|
||||||
|
OSConfigurator *_oscnf) :
|
||||||
|
NATCompiler(_db,fwname,_oscnf) , helper(this)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
string NATCompiler_pix::getNATACLname(Rule *rule,int nat_id)
|
||||||
|
{
|
||||||
|
int n=-1;
|
||||||
|
string res;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
n++;
|
||||||
|
ostringstream os;
|
||||||
|
os << rule->getUniqueId() << "." << nat_id << "." << n;
|
||||||
|
res=os.str();
|
||||||
|
} while (nat_acl_names.count(res)!=0);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
string NATCompiler_pix::getNATACLname(Rule *rule,string suffix)
|
||||||
|
{
|
||||||
|
int n=-1;
|
||||||
|
string res;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
n++;
|
||||||
|
ostringstream os;
|
||||||
|
os << rule->getUniqueId();
|
||||||
|
if (!suffix.empty()) os << "." << suffix;
|
||||||
|
os << "." << n;
|
||||||
|
res=os.str();
|
||||||
|
} while (nat_acl_names.count(res)!=0);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int NATCompiler_pix::prolog()
|
||||||
|
{
|
||||||
|
global_pool_no=1;
|
||||||
|
|
||||||
|
final_ruleset=new NAT();
|
||||||
|
fw->add( final_ruleset );
|
||||||
|
|
||||||
|
return NATCompiler::prolog();
|
||||||
|
}
|
||||||
|
|
||||||
|
string NATCompiler_pix::debugPrintRule(Rule *r)
|
||||||
|
{
|
||||||
|
NATRule *rule=NATRule::cast(r);
|
||||||
|
|
||||||
|
Interface *iface1 = getCachedFwInterface( rule->getStr("nat_iface_orig") );
|
||||||
|
Interface *iface2 = getCachedFwInterface( rule->getStr("nat_iface_trn") );
|
||||||
|
string iface1_name=(iface1!=NULL)?iface1->getName():"";
|
||||||
|
string iface2_name=(iface2!=NULL)?iface2->getName():"";
|
||||||
|
|
||||||
|
ostringstream os;
|
||||||
|
|
||||||
|
switch (rule->getRuleType())
|
||||||
|
{
|
||||||
|
case NATRule::NONAT:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NATRule::SNAT:
|
||||||
|
{
|
||||||
|
if ( ! rule->exists("nat_cmd") ) break;
|
||||||
|
NATCmd *natcmd=nat_commands[ rule->getInt("nat_cmd") ];
|
||||||
|
if (natcmd!=NULL)
|
||||||
|
{
|
||||||
|
os <<" NATCmd: ";
|
||||||
|
os << " rule=[" << natcmd->rule_label << "]";
|
||||||
|
os << " id=" << natcmd->nat_id;
|
||||||
|
os << " rule=" << natcmd->rule_label;
|
||||||
|
os << " nat_acl_name=" << natcmd->nat_acl_name;
|
||||||
|
os << " (" << nat_acl_names[natcmd->nat_acl_name] << ")";
|
||||||
|
os << " o_src=" << natcmd->o_src->getAddress().toString();
|
||||||
|
os << " o_dst=" << natcmd->o_dst->getAddress().toString();
|
||||||
|
os << " o_srv=" << natcmd->o_srv->getName();
|
||||||
|
os << " o_iface=" << natcmd->o_iface->getLabel();
|
||||||
|
os << " t_addr=" << natcmd->t_addr->getAddress().toString();
|
||||||
|
os << " t_iface=" << natcmd->t_iface->getLabel();
|
||||||
|
os << " ignore_global=" << string((natcmd->ignore_global)?"1":"0");
|
||||||
|
os << " ignore_nat=" << string((natcmd->ignore_nat)?"1":"0");
|
||||||
|
os << " ignore_nat_and_print_acl=" << string((natcmd->ignore_nat_and_print_acl)?"1":"0");
|
||||||
|
os << " use_nat_0_0=" << string((rule->getBool("use_nat_0_0"))?"1":"0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NATRule::DNAT:
|
||||||
|
{
|
||||||
|
if ( ! rule->exists("sc_cmd") ) break;
|
||||||
|
StaticCmd *scmd=static_commands[ rule->getInt("sc_cmd") ];
|
||||||
|
if (scmd!=NULL)
|
||||||
|
{
|
||||||
|
os << " StaticCmd:";
|
||||||
|
os << " acl=" << scmd->acl_name;
|
||||||
|
os << " (" << nat_acl_names[scmd->acl_name] << ")";
|
||||||
|
os << " iaddr=" << scmd->iaddr->getAddress().toString();
|
||||||
|
os << " oaddr=" << scmd->oaddr->getAddress().toString();
|
||||||
|
os << " osrc=" << scmd->osrc->getAddress().toString();
|
||||||
|
os << " osrv=" << scmd->osrv->getName();
|
||||||
|
os << " tsrv=" << scmd->tsrv->getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: ; // TODO: should actually be always_assert
|
||||||
|
}
|
||||||
|
|
||||||
|
return NATCompiler::debugPrintRule(rule)+
|
||||||
|
" "+iface1_name+" "+iface2_name+
|
||||||
|
" (type="+rule->getRuleTypeAsString()+") "+
|
||||||
|
"use_nat_0_0=" + string((rule->getBool("use_nat_0_0"))?"1":"0") + " " +
|
||||||
|
os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NATCompiler_pix::storeProcessedRules::processNext()
|
||||||
|
{
|
||||||
|
NATCompiler_pix *pix_comp=dynamic_cast<NATCompiler_pix*>(compiler);
|
||||||
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
pix_comp->final_ruleset->add(rule);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
list<triplet> NATCompiler_pix::findDNATForAddress(Address *src,
|
||||||
|
Address *dst,
|
||||||
|
Service *srv)
|
||||||
|
{
|
||||||
|
list<triplet> res;
|
||||||
|
map<string,triplet> res_dict;
|
||||||
|
|
||||||
|
for (FWObject::iterator i=final_ruleset->begin();
|
||||||
|
i!=final_ruleset->end(); ++i)
|
||||||
|
{
|
||||||
|
NATRule *rule=NATRule::cast(*i);
|
||||||
|
|
||||||
|
switch (rule->getRuleType())
|
||||||
|
{
|
||||||
|
case NATRule::DNAT:
|
||||||
|
{
|
||||||
|
Address *osrc=getFirstOSrc(rule); assert(osrc);
|
||||||
|
Address *odst=getFirstODst(rule); assert(odst);
|
||||||
|
Service *osrv=getFirstOSrv(rule); assert(osrv);
|
||||||
|
|
||||||
|
Address *tsrc=getFirstTSrc(rule); assert(tsrc);
|
||||||
|
Address *tdst=getFirstTDst(rule); assert(tdst);
|
||||||
|
Service *tsrv=getFirstTSrv(rule); assert(tsrv);
|
||||||
|
|
||||||
|
if (src->getAddress()==osrc->getAddress() &&
|
||||||
|
(osrv->isAny() || srv->getId()==tsrv->getId()) &&
|
||||||
|
dst->getAddress()==tdst->getAddress())
|
||||||
|
{
|
||||||
|
if (osrv->isAny())
|
||||||
|
{
|
||||||
|
triplet tr(src,odst,srv);
|
||||||
|
res_dict[tr.hash()] = tr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
triplet tr(src,odst,osrv);
|
||||||
|
res_dict[tr.hash()] = tr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: ; // TODO: should actually be always_assert
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (map<string,triplet>::iterator i=res_dict.begin();
|
||||||
|
i!=res_dict.end(); ++i)
|
||||||
|
{
|
||||||
|
res.push_back(i->second);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool NATCompiler_pix::VerifyRules::processNext()
|
||||||
|
{
|
||||||
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
string vers=compiler->fw->getStr("version");
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
bool version_lt_63= ( compiler->fw->getStr("platform")=="pix" &&
|
||||||
|
libfwbuilder::XMLTools::version_compare(compiler->fw->getStr("version"),"6.3")<0); // fwsm is always above 6.3 - its OS is based on 6.3
|
||||||
|
|
||||||
|
|
||||||
|
RuleElementOSrc *osrc=rule->getOSrc(); assert(osrc);
|
||||||
|
RuleElementODst *odst=rule->getODst(); assert(odst);
|
||||||
|
RuleElementOSrv *osrv=rule->getOSrv(); assert(osrv);
|
||||||
|
|
||||||
|
RuleElementTSrc *tsrc=rule->getTSrc(); assert(tsrc);
|
||||||
|
RuleElementTDst *tdst=rule->getTDst(); assert(tdst);
|
||||||
|
RuleElementTSrv *tsrv=rule->getTSrv(); assert(tsrv);
|
||||||
|
|
||||||
|
if (rule->getRuleType()==NATRule::LB)
|
||||||
|
compiler->abort("Load balancing rules are not supported. Rule "+rule->getLabel());
|
||||||
|
|
||||||
|
if (rule->getRuleType()==NATRule::NONAT && (!osrv->isAny() || !tsrv->isAny()))
|
||||||
|
compiler->abort("'no nat' rules should have no services");
|
||||||
|
|
||||||
|
|
||||||
|
if (osrc->getNeg() ||
|
||||||
|
odst->getNeg() ||
|
||||||
|
osrv->getNeg() ||
|
||||||
|
tsrc->getNeg() ||
|
||||||
|
tdst->getNeg() ||
|
||||||
|
tsrv->getNeg())
|
||||||
|
compiler->abort("Negation is not supported in NAT rules. Rule "+rule->getLabel());
|
||||||
|
|
||||||
|
if (rule->getRuleType()==NATRule::SNAT)
|
||||||
|
{
|
||||||
|
// if ( tsrc->size()!=1)
|
||||||
|
// compiler->abort("There should be no more than one object in translated source in the rule "+rule->getLabel());
|
||||||
|
|
||||||
|
if ( ! odst->isAny() && version_lt_63) // can do on fwsm
|
||||||
|
{
|
||||||
|
compiler->warning("Original destination is ignored in 'nat' NAT rules when compiling for PIX v6.2 and earlier. Rule "+rule->getLabel());
|
||||||
|
odst->clearChildren();
|
||||||
|
odst->setAnyElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule->getRuleType()==NATRule::DNAT)
|
||||||
|
{
|
||||||
|
if ( odst->size()!=1 && version_lt_63)
|
||||||
|
compiler->abort("There should be no more than one object in original destination in the rule "+rule->getLabel());
|
||||||
|
|
||||||
|
if ( ! osrc->isAny() && version_lt_63)
|
||||||
|
compiler->warning("Original source is ignored in 'static' NAT rules when compiling for PIX v6.2 and earlier. Rule "+rule->getLabel());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (osrv->size()!=1 && !tsrv->isAny())
|
||||||
|
compiler->abort("Can not translate multiple services into one service in one rule. Rule: "+rule->getLabel());
|
||||||
|
|
||||||
|
if (tsrv->size()!=1)
|
||||||
|
compiler->abort("Translated service should be 'Original' or should contain single object. Rule: "+rule->getLabel());
|
||||||
|
|
||||||
|
if ( Group::cast( compiler->getFirstTSrv(rule) )!=NULL)
|
||||||
|
compiler->abort("Can not use group in translated service. Rule "+rule->getLabel());
|
||||||
|
|
||||||
|
if (rule->getRuleType()==NATRule::SNetnat && !tsrc->isAny() )
|
||||||
|
{
|
||||||
|
Network *a1=Network::cast(compiler->getFirstOSrc(rule));
|
||||||
|
Network *a2=Network::cast(compiler->getFirstTSrc(rule));
|
||||||
|
if ( a1==NULL || a2==NULL ||
|
||||||
|
a1->getNetmask().getLength()!=a2->getNetmask().getLength() )
|
||||||
|
compiler->abort("Original and translated source should both be networks of the same size . Rule "+rule->getLabel());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule->getRuleType()==NATRule::DNetnat && !tsrc->isAny() )
|
||||||
|
{
|
||||||
|
Network *a1=Network::cast(compiler->getFirstODst(rule));
|
||||||
|
Network *a2=Network::cast(compiler->getFirstTDst(rule));
|
||||||
|
if ( a1==NULL || a2==NULL ||
|
||||||
|
a1->getNetmask().getLength()!=a2->getNetmask().getLength() )
|
||||||
|
compiler->abort("Original and translated destination should both be networks of the same size . Rule "+rule->getLabel());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule->getRuleType()==NATRule::SNetnat) rule->setRuleType(NATRule::SNAT);
|
||||||
|
if (rule->getRuleType()==NATRule::DNetnat) rule->setRuleType(NATRule::DNAT);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool NATCompiler_pix::AssignInterface::processNext()
|
||||||
|
{
|
||||||
|
Helper helper(compiler);
|
||||||
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
Address *a1=NULL;
|
||||||
|
Address *a2=NULL;
|
||||||
|
|
||||||
|
if (rule->getRuleType()==NATRule::SNAT) {
|
||||||
|
a1=compiler->getFirstOSrc(rule);
|
||||||
|
a2=compiler->getFirstTSrc(rule);
|
||||||
|
}
|
||||||
|
if (rule->getRuleType()==NATRule::DNAT) {
|
||||||
|
a1=compiler->getFirstODst(rule);
|
||||||
|
a2=compiler->getFirstTDst(rule);
|
||||||
|
}
|
||||||
|
if (rule->getRuleType()==NATRule::NONAT) {
|
||||||
|
a1=compiler->getFirstOSrc(rule);
|
||||||
|
a2=compiler->getFirstODst(rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(a1!=NULL && a2!=NULL);
|
||||||
|
|
||||||
|
rule->setStr("nat_iface_orig",helper.findInterfaceByNetzone(a1));
|
||||||
|
rule->setStr("nat_iface_trn", helper.findInterfaceByNetzone(a2));
|
||||||
|
|
||||||
|
if ( rule->getStr("nat_iface_orig")=="" )
|
||||||
|
compiler->abort("Object '"+a1->getName()+"' does not belong to any known network zone. Rule: "+rule->getLabel());
|
||||||
|
if ( rule->getStr("nat_iface_trn")=="" )
|
||||||
|
compiler->abort("Object '"+a2->getName()+"' does not belong to any known network zone. Rule: "+rule->getLabel());
|
||||||
|
|
||||||
|
// if ( rule->getStr("nat_iface_orig")==rule->getStr("nat_iface_trn"))
|
||||||
|
// compiler->abort("Objects '"+a1->getName()+"' and '"+a2->getName()+"' belong to the same network zone. Can not build NAT configuration. Rule: "+rule->getLabel());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NATCompiler_pix::verifyInterfaces::processNext()
|
||||||
|
{
|
||||||
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
#ifdef WRONG_CHECK
|
||||||
|
if ( rule->getStr("nat_iface_orig")!=rule->getStr("nat_iface_trn") )
|
||||||
|
{
|
||||||
|
if (rule->getRuleType()==NATRule::SNAT) {
|
||||||
|
Interface *iface1=
|
||||||
|
Interface::cast( rule->getRoot()->findInIndex(rule->getStr("nat_iface_orig")) );
|
||||||
|
Interface *iface2=
|
||||||
|
Interface::cast( rule->getRoot()->findInIndex(rule->getStr("nat_iface_trn")) );
|
||||||
|
|
||||||
|
if ( iface1->getSecurityLevel() <= iface2->getSecurityLevel() ) {
|
||||||
|
char lvl1[32];
|
||||||
|
char lvl2[32];
|
||||||
|
sprintf(lvl1,"%d",iface1->getSecurityLevel());
|
||||||
|
sprintf(lvl2,"%d",iface2->getSecurityLevel());
|
||||||
|
compiler->abort(
|
||||||
|
"Security level of internal interface "+
|
||||||
|
iface1->getName() + " (level "+ lvl1 +") "+
|
||||||
|
" set lower than that of external interface "+
|
||||||
|
iface2->getName() + " (level "+ lvl2 +") "+
|
||||||
|
" for NAT rule "+rule->getLabel());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NATCompiler_pix::verifyRuleElements::processNext()
|
||||||
|
{
|
||||||
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
Address *osrc=compiler->getFirstOSrc(rule); assert(osrc);
|
||||||
|
Address *odst=compiler->getFirstODst(rule); assert(odst);
|
||||||
|
Service *osrv=compiler->getFirstOSrv(rule); assert(osrv);
|
||||||
|
|
||||||
|
Address *tsrc=compiler->getFirstTSrc(rule); assert(tsrc);
|
||||||
|
Address *tdst=compiler->getFirstTDst(rule); assert(tdst);
|
||||||
|
Service *tsrv=compiler->getFirstTSrv(rule); assert(tsrv);
|
||||||
|
|
||||||
|
bool version_lt_63=libfwbuilder::XMLTools::version_compare(compiler->fw->getStr("version"),"6.3")<0;
|
||||||
|
|
||||||
|
if (rule->getRuleType()==NATRule::SNAT)
|
||||||
|
{
|
||||||
|
if ((! osrv->isAny() || ! tsrv->isAny()) && version_lt_63)
|
||||||
|
compiler->abort("only PIX v6.3 recognizes services in global NAT. Rule: "+rule->getLabel() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule->getRuleType()==NATRule::DNAT)
|
||||||
|
{
|
||||||
|
if (AddressRange::cast(odst) || AddressRange::cast(tdst))
|
||||||
|
compiler->abort(
|
||||||
|
"Address ranges are not supported in original destination or translated destination in NAT rule "+rule->getLabel() );
|
||||||
|
|
||||||
|
if (Network::isA(odst) && Network::isA(tdst))
|
||||||
|
{
|
||||||
|
Netmask n1=(Interface::cast(odst))?Netmask("255.255.255.255"):odst->getNetmask();
|
||||||
|
Netmask n2=(Interface::cast(tdst))?Netmask("255.255.255.255"):tdst->getNetmask();
|
||||||
|
|
||||||
|
if ( !(n1==n2) )
|
||||||
|
compiler->abort(
|
||||||
|
"Original and translated destination must be of the same size in the NAT rule "+rule->getLabel());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (osrv->getTypeName()!=tsrv->getTypeName())
|
||||||
|
compiler->abort("Original and translated services must be of the same type. Rule: "+rule->getLabel());
|
||||||
|
|
||||||
|
if (ICMPService::isA(osrv))
|
||||||
|
compiler->abort("ICMP services are not supported in static NAT. Rule: "+rule->getLabel());
|
||||||
|
|
||||||
|
if (TCPService::isA(osrv) || UDPService::isA(osrv))
|
||||||
|
{
|
||||||
|
int drs=osrv->getInt("dst_range_start");
|
||||||
|
int dre=osrv->getInt("dst_range_end");
|
||||||
|
|
||||||
|
if (drs!=dre)
|
||||||
|
compiler->abort("TCP or UDP service with a port range is not supported in NAT. Rule "+rule->getLabel());
|
||||||
|
}
|
||||||
|
if (TCPService::isA(tsrv) || UDPService::isA(tsrv))
|
||||||
|
{
|
||||||
|
int drs=tsrv->getInt("dst_range_start");
|
||||||
|
int dre=tsrv->getInt("dst_range_end");
|
||||||
|
|
||||||
|
if (drs!=dre)
|
||||||
|
compiler->abort("TCP or UDP service with a port range is not supported in NAT. Rule "+rule->getLabel());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NATCompiler_pix::fillTranslatedSrv::processNext()
|
||||||
|
{
|
||||||
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
Service *osrv_o=compiler->getFirstOSrv(rule);
|
||||||
|
Service *tsrv_o=compiler->getFirstTSrv(rule);
|
||||||
|
|
||||||
|
if ( ! osrv_o->isAny() && tsrv_o->isAny() ) {
|
||||||
|
RuleElementTSrv *tsrv=rule->getTSrv();
|
||||||
|
tsrv->addRef(osrv_o);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* unlike standard inspector addressRanges in the base class NATCompiler,
|
||||||
|
* this one does not expand address ranges in TSrc and TDst
|
||||||
|
*/
|
||||||
|
bool NATCompiler_pix::ExpandAddressRanges::processNext()
|
||||||
|
{
|
||||||
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
RuleElement *rel;
|
||||||
|
|
||||||
|
rel=rule->getOSrc(); assert(rel);
|
||||||
|
compiler->_expandAddressRanges(rule,rel);
|
||||||
|
rel=rule->getODst(); assert(rel);
|
||||||
|
compiler->_expandAddressRanges(rule,rel);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// if we want to support NAT rules with address ranges. For example,
|
||||||
|
// could compile these as a bunch of individual host translations
|
||||||
|
|
||||||
|
switch (rule->getRuleType())
|
||||||
|
{
|
||||||
|
case NATRule::SNAT:
|
||||||
|
rel=rule->getTSrc(); assert(rel);
|
||||||
|
compiler->_expandAddressRanges(rule,rel);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NATRule::DNAT:
|
||||||
|
rel=rule->getTDst(); assert(rel);
|
||||||
|
compiler->_expandAddressRanges(rule,rel);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* I assume that there is always only one object in ODst, TSrc and TDst
|
||||||
|
* rule elements. This should have been assured by inspector VerifyRules
|
||||||
|
*/
|
||||||
|
bool NATCompiler_pix::ReplaceFirewallObjectsODst::processNext()
|
||||||
|
{
|
||||||
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
list<FWObject*> cl;
|
||||||
|
RuleElementODst *rel;
|
||||||
|
Address *obj=NULL;
|
||||||
|
|
||||||
|
switch (rule->getRuleType()) {
|
||||||
|
|
||||||
|
case NATRule::Masq:
|
||||||
|
// case NATRule::Redirect:
|
||||||
|
return true;
|
||||||
|
case NATRule::DNAT:
|
||||||
|
rel=rule->getODst(); assert(rel);
|
||||||
|
obj=compiler->getFirstODst(rule); assert(obj!=NULL);
|
||||||
|
|
||||||
|
if (obj->getId()==compiler->getFwId() )
|
||||||
|
{
|
||||||
|
|
||||||
|
list<FWObject*> l2=compiler->fw->getByType(Interface::TYPENAME);
|
||||||
|
for (list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i) {
|
||||||
|
Interface *interface_=Interface::cast(*i);
|
||||||
|
|
||||||
|
if (! interface_->isLoopback() &&
|
||||||
|
interface_->isExt() ) cl.push_back(interface_);
|
||||||
|
}
|
||||||
|
if ( ! cl.empty() ) {
|
||||||
|
while (rel->size())
|
||||||
|
rel->remove( rel->front() );
|
||||||
|
|
||||||
|
for (FWObject::iterator i1=cl.begin(); i1!=cl.end(); ++i1)
|
||||||
|
{
|
||||||
|
rel->addRef( *i1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default: ; // TODO: should actually be always_assert
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NATCompiler_pix::ReplaceFirewallObjectsTSrc::processNext()
|
||||||
|
{
|
||||||
|
Helper helper(compiler);
|
||||||
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
list<FWObject*> cl;
|
||||||
|
RuleElementTSrc *rel;
|
||||||
|
Address *obj=NULL;
|
||||||
|
|
||||||
|
switch (rule->getRuleType()) {
|
||||||
|
|
||||||
|
case NATRule::Masq:
|
||||||
|
case NATRule::Redirect: return true;
|
||||||
|
|
||||||
|
case NATRule::SNAT:
|
||||||
|
{
|
||||||
|
int osrc_level=100;
|
||||||
|
Address *osrc=NULL;
|
||||||
|
Interface *osrc_iface=NULL;
|
||||||
|
|
||||||
|
if ( ! rule->getOSrc()->isAny())
|
||||||
|
{
|
||||||
|
osrc=compiler->getFirstOSrc(rule); assert(osrc!=NULL);
|
||||||
|
osrc_iface=compiler->getCachedFwInterface( helper.findInterfaceByNetzone(osrc ) );
|
||||||
|
osrc_level=osrc_iface->getSecurityLevel();
|
||||||
|
}
|
||||||
|
|
||||||
|
rel=rule->getTSrc(); assert(rel);
|
||||||
|
obj=compiler->getFirstTSrc(rule); assert(obj!=NULL);
|
||||||
|
|
||||||
|
if (obj->getId()==compiler->getFwId() )
|
||||||
|
{
|
||||||
|
|
||||||
|
/* if ODst is 'any', pick all interfaces with security level _less_ than
|
||||||
|
* level of the interface OSrc is associated with. If ODst is not 'any',
|
||||||
|
* find interface it is associated with and use only it.
|
||||||
|
*/
|
||||||
|
if (rule->getODst()->isAny())
|
||||||
|
{
|
||||||
|
list<FWObject*> l2=compiler->fw->getByType(Interface::TYPENAME);
|
||||||
|
for (list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i)
|
||||||
|
{
|
||||||
|
Interface *interface_=Interface::cast(*i);
|
||||||
|
|
||||||
|
if (interface_->getSecurityLevel()<osrc_level )
|
||||||
|
cl.push_back(interface_);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
Address *odst=compiler->getFirstODst(rule); assert(odst!=NULL);
|
||||||
|
Interface *odst_iface=compiler->getCachedFwInterface( helper.findInterfaceByNetzone(odst ) );
|
||||||
|
if (odst_iface!=NULL) cl.push_back(odst_iface);
|
||||||
|
}
|
||||||
|
if ( ! cl.empty() ) {
|
||||||
|
while (rel->size())
|
||||||
|
rel->remove( rel->front() );
|
||||||
|
|
||||||
|
for (FWObject::iterator i1=cl.begin(); i1!=cl.end(); ++i1)
|
||||||
|
{
|
||||||
|
rel->addRef( *i1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: ; // TODO: should actually be always_assert
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NATCompiler_pix::UseFirewallInterfaces::scanInterfaces(RuleElement *rel)
|
||||||
|
{
|
||||||
|
FWObject *o= rel->front();
|
||||||
|
if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
|
||||||
|
Address *obj=Address::cast(o);
|
||||||
|
if(obj==NULL)
|
||||||
|
compiler->abort("Broken rule element "+
|
||||||
|
rel->getTypeName()+
|
||||||
|
" in rule "+
|
||||||
|
NATRule::cast(rel->getParent())->getLabel()+
|
||||||
|
" ( found object with type "+
|
||||||
|
string((o!=NULL)?o->getTypeName():"<NULL>") +
|
||||||
|
")");
|
||||||
|
|
||||||
|
list<FWObject*> l2=compiler->fw->getByType(Interface::TYPENAME);
|
||||||
|
for (list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i)
|
||||||
|
{
|
||||||
|
Interface *interface_=Interface::cast(*i);
|
||||||
|
|
||||||
|
if (interface_->getAddress()==obj->getAddress())
|
||||||
|
{
|
||||||
|
rel->removeRef(obj);
|
||||||
|
rel->addRef(interface_);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NATCompiler_pix::UseFirewallInterfaces::processNext()
|
||||||
|
{
|
||||||
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
RuleElement *rel;
|
||||||
|
|
||||||
|
rel=rule->getODst(); assert(rel);
|
||||||
|
if (!rel->isAny()) scanInterfaces(rel);
|
||||||
|
|
||||||
|
rel=rule->getTSrc(); assert(rel);
|
||||||
|
if (!rel->isAny()) scanInterfaces(rel);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NATCompiler_pix::processNONATRules::processNext()
|
||||||
|
{
|
||||||
|
Helper helper(compiler);
|
||||||
|
NATCompiler_pix *pix_comp=dynamic_cast<NATCompiler_pix*>(compiler);
|
||||||
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
if (rule->getRuleType()==NATRule::NONAT) {
|
||||||
|
Address *osrc=compiler->getFirstOSrc(rule); assert(osrc);
|
||||||
|
Address *odst=compiler->getFirstODst(rule); assert(odst);
|
||||||
|
|
||||||
|
Interface *osrc_iface=compiler->getCachedFwInterface( helper.findInterfaceByNetzone(osrc ) );
|
||||||
|
Interface *odst_iface=compiler->getCachedFwInterface( helper.findInterfaceByNetzone(odst ) );
|
||||||
|
|
||||||
|
int osrc_level=osrc_iface->getSecurityLevel();
|
||||||
|
int odst_level=odst_iface->getSecurityLevel();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PIX has two types of NONAT rules, one is when connection goes from
|
||||||
|
* low security interface to the high security interface and another
|
||||||
|
* for the opposite
|
||||||
|
*/
|
||||||
|
if (osrc_level>odst_level)
|
||||||
|
{
|
||||||
|
rule->setInt("nonat_type",NONAT_NAT0);
|
||||||
|
nonat n0;
|
||||||
|
n0.i_iface=osrc_iface;
|
||||||
|
n0.o_iface=odst_iface;
|
||||||
|
n0.src=osrc;
|
||||||
|
n0.dst=odst;
|
||||||
|
n0.acl_name="nat0."+osrc_iface->getLabel();
|
||||||
|
n0.last=true;
|
||||||
|
|
||||||
|
pix_comp->nonat_rules[rule->getId()]= n0;
|
||||||
|
pix_comp->registerACL(n0.acl_name);
|
||||||
|
|
||||||
|
if ( pix_comp->first_nonat_rule_id[osrc_iface->getId()].empty() )
|
||||||
|
pix_comp->first_nonat_rule_id[osrc_iface->getId()]=rule->getId();
|
||||||
|
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
rule->setInt("nonat_type",NONAT_STATIC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NATCompiler_pix::createNATCmd::processNext()
|
||||||
|
{
|
||||||
|
// Helper helper(compiler);
|
||||||
|
NATCompiler_pix *pix_comp=dynamic_cast<NATCompiler_pix*>(compiler);
|
||||||
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
if (rule->getRuleType()==NATRule::SNAT)
|
||||||
|
{
|
||||||
|
Address *osrc=compiler->getFirstOSrc(rule); assert(osrc);
|
||||||
|
Address *odst=compiler->getFirstODst(rule); assert(osrc);
|
||||||
|
Service *osrv=compiler->getFirstOSrv(rule); assert(osrv);
|
||||||
|
Address *tsrc=compiler->getFirstTSrc(rule); assert(tsrc);
|
||||||
|
|
||||||
|
NATCmd *natcmd=new NATCmd();
|
||||||
|
|
||||||
|
natcmd->nat_id=nat_id_counter;
|
||||||
|
natcmd->rule_label=rule->getLabel();
|
||||||
|
|
||||||
|
natcmd->o_src = osrc;
|
||||||
|
natcmd->o_dst = odst;
|
||||||
|
natcmd->o_srv = osrv;
|
||||||
|
natcmd->o_iface = compiler->getCachedFwInterface( rule->getStr("nat_iface_orig") );
|
||||||
|
natcmd->t_addr = tsrc;
|
||||||
|
natcmd->t_iface = compiler->getCachedFwInterface( rule->getStr("nat_iface_trn" ) );
|
||||||
|
|
||||||
|
natcmd->nat_acl_name = pix_comp->getNATACLname(rule,"");
|
||||||
|
pix_comp->registerACL(natcmd->nat_acl_name);
|
||||||
|
|
||||||
|
if (Interface::cast(tsrc)!=NULL || natcmd->t_iface->isDyn())
|
||||||
|
{
|
||||||
|
natcmd->type=INTERFACE;
|
||||||
|
} else {
|
||||||
|
if (Network::cast(tsrc))
|
||||||
|
{
|
||||||
|
natcmd->type=NETWORK_ADDRESS;
|
||||||
|
} else {
|
||||||
|
if (AddressRange::cast(tsrc)) natcmd->type=ADDRESS_RANGE;
|
||||||
|
else natcmd->type=SINGLE_ADDRESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
natcmd->ignore_nat=natcmd->ignore_nat_and_print_acl=natcmd->ignore_global=false;
|
||||||
|
natcmd->use_nat_0_0 = rule->getBool("use_nat_0_0");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "nat ... outside" is only supported in PIX 6.2
|
||||||
|
*/
|
||||||
|
natcmd->outside= ( natcmd->o_iface->getSecurityLevel()<natcmd->t_iface->getSecurityLevel());
|
||||||
|
|
||||||
|
if (natcmd->outside && compiler->fw->getStr("platform")=="pix" &&
|
||||||
|
libfwbuilder::XMLTools::version_compare(compiler->fw->getStr("version"),"6.2")<0 )
|
||||||
|
compiler->abort("Bi-Directional NAT of source addresses is only supported in PIX 6.2 and newer. Rule "+rule->getLabel());
|
||||||
|
|
||||||
|
/*
|
||||||
|
* map is sorted container, this means that objects are going to be arranged
|
||||||
|
* in nat_commands in the order of the key.
|
||||||
|
*/
|
||||||
|
pix_comp->nat_commands[nat_id_counter]= natcmd;
|
||||||
|
rule->setInt("nat_cmd",nat_id_counter);
|
||||||
|
nat_id_counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NATCompiler_pix::createStaticCmd::processNext()
|
||||||
|
{
|
||||||
|
NATCompiler_pix *pix_comp=dynamic_cast<NATCompiler_pix*>(compiler);
|
||||||
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
if (rule->getRuleType()==NATRule::DNAT)
|
||||||
|
{
|
||||||
|
Address *osrc=compiler->getFirstOSrc(rule); assert(osrc);
|
||||||
|
Address *odst=compiler->getFirstODst(rule); assert(odst);
|
||||||
|
Service *osrv=compiler->getFirstOSrv(rule); assert(osrv);
|
||||||
|
Address *tdst=compiler->getFirstTDst(rule); assert(tdst);
|
||||||
|
Service *tsrv=compiler->getFirstTSrv(rule); assert(tsrv);
|
||||||
|
|
||||||
|
StaticCmd *scmd=new StaticCmd();
|
||||||
|
|
||||||
|
scmd->acl_name = pix_comp->getNATACLname(rule,"");
|
||||||
|
pix_comp->registerACL(scmd->acl_name);
|
||||||
|
scmd->rule=rule->getLabel();
|
||||||
|
// source and destination addresses are swapped here because
|
||||||
|
// access lists used for NAT should have 'real' addresses in source
|
||||||
|
scmd->iaddr=tdst;
|
||||||
|
scmd->oaddr=odst;
|
||||||
|
scmd->osrc= osrc;
|
||||||
|
scmd->osrv= osrv;
|
||||||
|
scmd->tsrv= tsrv;
|
||||||
|
scmd->ignore_scmd_and_print_acl=false;
|
||||||
|
|
||||||
|
pix_comp->static_commands[sc_id_counter]=scmd;
|
||||||
|
rule->setInt("sc_cmd",sc_id_counter);
|
||||||
|
|
||||||
|
sc_id_counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this processor uses slurp to make sure all previous processors ran before
|
||||||
|
* it starts scanning rules.
|
||||||
|
*/
|
||||||
|
bool NATCompiler_pix::mergeNATCmd::processNext()
|
||||||
|
{
|
||||||
|
NATCompiler_pix *pix_comp=dynamic_cast<NATCompiler_pix*>(compiler);
|
||||||
|
|
||||||
|
slurp();
|
||||||
|
if (tmp_queue.size()==0) return false;
|
||||||
|
|
||||||
|
for (deque<Rule*>::iterator k=tmp_queue.begin(); k!=tmp_queue.end(); ++k)
|
||||||
|
{
|
||||||
|
NATRule *rule = NATRule::cast( *k );
|
||||||
|
|
||||||
|
if (rule->getRuleType()==NATRule::DNAT)
|
||||||
|
{
|
||||||
|
StaticCmd *scmd=pix_comp->static_commands[rule->getInt("sc_cmd")];
|
||||||
|
|
||||||
|
for (map<int,StaticCmd*>::iterator i1=pix_comp->static_commands.begin();
|
||||||
|
i1!=pix_comp->static_commands.end(); ++i1)
|
||||||
|
{
|
||||||
|
StaticCmd *sc=(*i1).second;
|
||||||
|
if (scmd==sc) break;
|
||||||
|
|
||||||
|
if (*(scmd->oaddr) == *(sc->oaddr) &&
|
||||||
|
*(scmd->iaddr) == *(sc->iaddr) &&
|
||||||
|
*(scmd->osrv) == *(sc->osrv) &&
|
||||||
|
*(scmd->tsrv) == *(sc->tsrv))
|
||||||
|
{
|
||||||
|
/* rule 'sc' is above rule 'scmd', we need to print 'static' command
|
||||||
|
* only in the last rule using the same access list. That's why we set
|
||||||
|
* flag ignore_scmd_and_print acl in sc and not in scmd
|
||||||
|
*/
|
||||||
|
|
||||||
|
scmd->acl_name = sc->acl_name;
|
||||||
|
sc->ignore_scmd_and_print_acl=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule->getRuleType()==NATRule::SNAT)
|
||||||
|
{
|
||||||
|
NATCmd *natcmd=pix_comp->nat_commands[ rule->getInt("nat_cmd") ];
|
||||||
|
|
||||||
|
for (map<int,NATCmd*>::iterator i1=pix_comp->nat_commands.begin();
|
||||||
|
i1!=pix_comp->nat_commands.end(); ++i1)
|
||||||
|
{
|
||||||
|
NATCmd *nc=(*i1).second;
|
||||||
|
/* since map nat_commands is sorted by the key, we only have to scan it
|
||||||
|
* until we hit natcmd
|
||||||
|
*/
|
||||||
|
if (natcmd==nc) break;
|
||||||
|
|
||||||
|
IPAddress a1=natcmd->t_addr->getAddress();
|
||||||
|
IPAddress a2=nc->t_addr->getAddress();
|
||||||
|
|
||||||
|
Interface *int1=natcmd->t_iface;
|
||||||
|
Interface *int2=nc->t_iface;
|
||||||
|
|
||||||
|
if ( a1 == a2 && int1->getId()==int2->getId() )
|
||||||
|
{
|
||||||
|
natcmd->ignore_global=true;
|
||||||
|
natcmd->nat_id=nc->nat_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (map<int,NATCmd*>::iterator i1=pix_comp->nat_commands.begin();
|
||||||
|
i1!=pix_comp->nat_commands.end(); ++i1)
|
||||||
|
{
|
||||||
|
NATCmd *nc=(*i1).second;
|
||||||
|
/* since map nat_commands is sorted by the key, we only have to scan it
|
||||||
|
* until we hit natcmd
|
||||||
|
*/
|
||||||
|
if (natcmd==nc) break;
|
||||||
|
if (nc->ignore_nat) continue;
|
||||||
|
|
||||||
|
/* using operator==(const Address &o1,const Address &o2) here */
|
||||||
|
|
||||||
|
if ( *(natcmd->o_src) == *(nc->o_src) &&
|
||||||
|
*(natcmd->o_dst) == *(nc->o_dst) &&
|
||||||
|
*(natcmd->o_srv) == *(nc->o_srv) &&
|
||||||
|
natcmd->o_iface->getId() == nc->o_iface->getId() )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* there is another nat rule (rule #2) with the same "original"
|
||||||
|
* addresses and the same interface. We can drop this nat rule, but need
|
||||||
|
* to merge its global pool with pool of the rule #2.
|
||||||
|
*
|
||||||
|
* This nat rule could have been sharing a global pool with some other
|
||||||
|
* nat rule; in this case we need to find this other rule and also
|
||||||
|
* reassign it to the global pool of the rule #2.
|
||||||
|
*/
|
||||||
|
natcmd->ignore_nat=true;
|
||||||
|
|
||||||
|
for (map<int,NATCmd*>::iterator i2=pix_comp->nat_commands.begin();
|
||||||
|
i2!=pix_comp->nat_commands.end(); ++i2)
|
||||||
|
{
|
||||||
|
NATCmd *nc2=i2->second;
|
||||||
|
if (natcmd->nat_id == nc2->nat_id)
|
||||||
|
nc2->nat_id=nc->nat_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
natcmd->nat_id=nc->nat_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!natcmd->use_nat_0_0)
|
||||||
|
{
|
||||||
|
for (map<int,NATCmd*>::iterator i1=pix_comp->nat_commands.begin();
|
||||||
|
i1!=pix_comp->nat_commands.end(); ++i1)
|
||||||
|
{
|
||||||
|
NATCmd *nc=(*i1).second;
|
||||||
|
/* since map nat_commands is sorted by the key, we only have to scan it
|
||||||
|
* until we hit natcmd
|
||||||
|
*/
|
||||||
|
if (natcmd==nc) break;
|
||||||
|
|
||||||
|
/* ignore nat natcmd entries for rules where we won't print 'nat'
|
||||||
|
* command or use 'nat 0' command since this means we won't print
|
||||||
|
* access-list for those rules and hense can not merge lists
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (nc->ignore_nat) continue;
|
||||||
|
if (nc->use_nat_0_0) continue;
|
||||||
|
|
||||||
|
if ( natcmd->nat_id==nc->nat_id &&
|
||||||
|
natcmd->t_addr == nc->t_addr &&
|
||||||
|
natcmd->o_iface->getId() == nc->o_iface->getId() )
|
||||||
|
{
|
||||||
|
/* two nat commands with the same id, the same interface and the same
|
||||||
|
* translated address, but different osrc and odst. OSrc and ODst must
|
||||||
|
* be different, otherwise these two commands would have been merged
|
||||||
|
* in the previous cycle. We can merge access lists and drop one of
|
||||||
|
* these nat commands. We merge ACLs by assigning them the same name.
|
||||||
|
*/
|
||||||
|
|
||||||
|
natcmd->nat_acl_name = nc->nat_acl_name;
|
||||||
|
nc->ignore_nat_and_print_acl=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The goal of this processor is to find SNAT rules that could be
|
||||||
|
* translated as "nat (interface) 0.0.0.0 0.0.0.0. These rules should
|
||||||
|
* have the same network object in OSrc that is used to define
|
||||||
|
* interface's network zone. The logic is simple: if network "A" is a
|
||||||
|
* network zone for internal interface, then only packets from this
|
||||||
|
* network can hit it and therefore there is no need to check source
|
||||||
|
* address once more in the "nat" rule.
|
||||||
|
*
|
||||||
|
* We also check for ODst and OSrv, because if the destination or the
|
||||||
|
* service are defined, then this optimization can not be done.
|
||||||
|
*
|
||||||
|
* This optimization can be turned off using checkbutton in the
|
||||||
|
* "Firewall" tab.
|
||||||
|
*
|
||||||
|
* call this processor really early, when groups have not been
|
||||||
|
* expanded yet. At this point both NAT rule type and interfaces it
|
||||||
|
* is associated with are unknown yet. We have to partially repeat
|
||||||
|
* algorithms used in other rule processors to determine NAT rule type
|
||||||
|
* and interface.
|
||||||
|
*
|
||||||
|
* We do this optimization in two steps:
|
||||||
|
*
|
||||||
|
* 1. in this rule processor we replace object in OSrc with firewall's
|
||||||
|
* interface. This way we can still use other rule processors that
|
||||||
|
* determine rule type and assign it to interfaces, but rule won't be
|
||||||
|
* split onto multiple rules because of objects in OSrc. We also set
|
||||||
|
* boolean flags "clear_osrc" and "use_nat_0_0" on the rule.
|
||||||
|
*
|
||||||
|
* 2. further down in rule processor clearOSrc we check the flag and
|
||||||
|
* clear OSrc if it is set.
|
||||||
|
*
|
||||||
|
* 3. flag "use_nat_0_0" is used in printRule processor.
|
||||||
|
*/
|
||||||
|
bool NATCompiler_pix::optimizeDefaultNAT::processNext()
|
||||||
|
{
|
||||||
|
// NATCompiler_pix *pix_comp=dynamic_cast<NATCompiler_pix*>(compiler);
|
||||||
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
RuleElementOSrc *osrc=rule->getOSrc();
|
||||||
|
RuleElementOSrv *osrv=rule->getOSrv();
|
||||||
|
RuleElementODst *odst=rule->getODst();
|
||||||
|
RuleElementTSrc *tsrc=rule->getTSrc();
|
||||||
|
RuleElementTDst *tdst=rule->getTDst();
|
||||||
|
|
||||||
|
if (osrc->size()>1) return true;
|
||||||
|
if (osrc->isAny()) return true;
|
||||||
|
if (!osrv->isAny()) return true;
|
||||||
|
if (!odst->isAny()) return true;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* can't use RuleElementOSrc::getFirst(bool dereference) because it
|
||||||
|
* returns Address::cast(o), but child element of rule element may be
|
||||||
|
* a group when this processor is called.
|
||||||
|
*/
|
||||||
|
FWObject *o=osrc->front();
|
||||||
|
string osrc_id;
|
||||||
|
if (FWReference::cast(o)!=NULL) osrc_id=FWReference::cast(o)->getPointerId();
|
||||||
|
else osrc_id=o->getId();
|
||||||
|
|
||||||
|
if ( ( !tsrc->isAny() && tdst->isAny()) ||
|
||||||
|
( !osrc->isAny() && odst->isAny() && tsrc->isAny() && tdst->isAny() )
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// this rule type is SNAT or NONAT
|
||||||
|
|
||||||
|
list<FWObject*> l2=compiler->fw->getByType(Interface::TYPENAME);
|
||||||
|
for (list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i)
|
||||||
|
{
|
||||||
|
Interface *iface=Interface::cast(*i);
|
||||||
|
|
||||||
|
if (iface->getStr("orig_netzone_id")==osrc_id )
|
||||||
|
{
|
||||||
|
rule->setBool("clear_osrc",true);
|
||||||
|
rule->setBool("use_nat_0_0",true);
|
||||||
|
osrc->clearChildren();
|
||||||
|
osrc->addRef(iface);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NATCompiler_pix::clearOSrc::processNext()
|
||||||
|
{
|
||||||
|
// NATCompiler_pix *pix_comp=dynamic_cast<NATCompiler_pix*>(compiler);
|
||||||
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
|
||||||
|
if (rule->getBool("clear_osrc"))
|
||||||
|
{
|
||||||
|
RuleElementOSrc *osrc=rule->getOSrc();
|
||||||
|
osrc->clearChildren();
|
||||||
|
osrc->setAnyElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NATCompiler_pix::processMultiAddressObjectsInRE::processNext()
|
||||||
|
{
|
||||||
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
RuleElement *re=RuleElement::cast( rule->getFirstByType(re_type) );
|
||||||
|
|
||||||
|
for (FWObject::iterator i=re->begin(); i!=re->end(); i++)
|
||||||
|
{
|
||||||
|
FWObject *o= *i;
|
||||||
|
if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
|
||||||
|
MultiAddress *atrt = MultiAddress::cast(o);
|
||||||
|
if (atrt!=NULL && atrt->isRunTime())
|
||||||
|
compiler->abort("Run-time AddressTable and DNSName objects are not supported. Rule " + rule->getLabel());
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool NATCompiler_pix::SuppressDuplicateNONATStatics::processNext()
|
||||||
|
{
|
||||||
|
Helper helper(compiler);
|
||||||
|
// NATCompiler_pix *pix_comp=dynamic_cast<NATCompiler_pix*>(compiler);
|
||||||
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
|
||||||
|
if (rule->getRuleType()== NATRule::NONAT &&
|
||||||
|
rule->getInt("nonat_type")==NONAT_STATIC)
|
||||||
|
{
|
||||||
|
Address *osrc=compiler->getFirstOSrc(rule); assert(osrc);
|
||||||
|
Address *odst=compiler->getFirstODst(rule); assert(odst);
|
||||||
|
|
||||||
|
nonat_static_parameters sp;
|
||||||
|
sp.iface1= helper.findInterfaceByNetzone(osrc );
|
||||||
|
sp.iface2= helper.findInterfaceByNetzone(odst );
|
||||||
|
sp.addr=odst->getAddress();
|
||||||
|
sp.mask=odst->getNetmask();
|
||||||
|
|
||||||
|
for (deque<nonat_static_parameters>::iterator i=all_nonat_statics.begin();
|
||||||
|
i!=all_nonat_statics.end(); ++i )
|
||||||
|
{
|
||||||
|
if ( i->iface1==sp.iface1 &&
|
||||||
|
i->iface2==sp.iface2 &&
|
||||||
|
i->addr==sp.addr &&
|
||||||
|
i->mask==sp.mask ) return true;
|
||||||
|
}
|
||||||
|
all_nonat_statics.push_back(sp);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
NATCompiler_pix::DetectOverlap::~DetectOverlap() {};
|
||||||
|
|
||||||
|
bool NATCompiler_pix::DetectOverlap::checkOverlapping(
|
||||||
|
const libfwbuilder::Address &addr1,
|
||||||
|
const libfwbuilder::IPAddress &addr2)
|
||||||
|
{
|
||||||
|
if (AddressRange::isA(&addr1))
|
||||||
|
{
|
||||||
|
const IPAddress a1=AddressRange::constcast(&addr1)->getRangeStart();
|
||||||
|
const IPAddress a2=AddressRange::constcast(&addr1)->getRangeEnd();
|
||||||
|
return (addr2==a1 || addr2==a2 || (addr2>a1 && addr2<a2));
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return addr1.getAddress() == addr2 ||
|
||||||
|
IPNetwork(addr1.getAddress(),addr1.getNetmask()).belongs(addr2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string NATCompiler_pix::DetectOverlap::printGlobalPoolAddress(const Address &pool)
|
||||||
|
{
|
||||||
|
if (AddressRange::isA(&pool))
|
||||||
|
{
|
||||||
|
const IPAddress a1=AddressRange::constcast(&pool)->getRangeStart();
|
||||||
|
const IPAddress a2=AddressRange::constcast(&pool)->getRangeEnd();
|
||||||
|
return a1.toString()+"-"+a2.toString();
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return pool.getAddress().toString()+"/"+pool.getNetmask().toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NATCompiler_pix::DetectGlobalPoolProblems::processNext()
|
||||||
|
{
|
||||||
|
NATCompiler_pix *pix_comp=dynamic_cast<NATCompiler_pix*>(compiler);
|
||||||
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
if (rule->getRuleType()== NATRule::SNAT )
|
||||||
|
{
|
||||||
|
NATCmd *natcmd=pix_comp->nat_commands[ rule->getInt("nat_cmd") ];
|
||||||
|
|
||||||
|
if (natcmd->ignore_global) return true;
|
||||||
|
|
||||||
|
if (natcmd->type!= INTERFACE)
|
||||||
|
{
|
||||||
|
if (checkOverlapping(*(natcmd->t_addr),
|
||||||
|
natcmd->t_iface->getAddress()))
|
||||||
|
compiler->abort("Global pool "
|
||||||
|
+printGlobalPoolAddress(*(natcmd->t_addr))
|
||||||
|
+" overlaps with interface address. Rule "
|
||||||
|
+rule->getLabel());
|
||||||
|
|
||||||
|
IPNetwork iface_net(natcmd->t_iface->getAddress(),
|
||||||
|
natcmd->t_iface->getNetmask());
|
||||||
|
|
||||||
|
if (checkOverlapping(*(natcmd->t_addr),
|
||||||
|
iface_net.getBroadcastAddress()) ||
|
||||||
|
checkOverlapping(*(natcmd->t_addr),
|
||||||
|
iface_net.getAddress()) )
|
||||||
|
compiler->warning("Global pool "
|
||||||
|
+printGlobalPoolAddress(*(natcmd->t_addr))
|
||||||
|
+" overlaps with broadcast address. Rule "
|
||||||
|
+rule->getLabel());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (map<int,NATCmd*>::iterator i1=pix_comp->nat_commands.begin();
|
||||||
|
i1!=pix_comp->nat_commands.end(); ++i1)
|
||||||
|
{
|
||||||
|
NATCmd *nc=(*i1).second;
|
||||||
|
/* since map nat_commands is sorted by the key, we only have to scan it
|
||||||
|
* until we hit natcmd
|
||||||
|
*/
|
||||||
|
if (nc->ignore_global) continue;
|
||||||
|
if (natcmd==nc) break;
|
||||||
|
|
||||||
|
Interface *int1=natcmd->t_iface;
|
||||||
|
Interface *int2=nc->t_iface;
|
||||||
|
|
||||||
|
if ( int1->getId()==int2->getId() )
|
||||||
|
{
|
||||||
|
if ( ! fwcompiler::_find_obj_intersection(natcmd->t_addr,nc->t_addr).empty() )
|
||||||
|
{
|
||||||
|
compiler->abort(string("Global pool overlapping: \n")
|
||||||
|
+" "+rule->getLabel()+" : "
|
||||||
|
+printGlobalPoolAddress(*(natcmd->t_addr))
|
||||||
|
+"\n"
|
||||||
|
+" "+nc->rule_label+" : "
|
||||||
|
+printGlobalPoolAddress(*(nc->t_addr)) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool NATCompiler_pix::DetectOverlappingGlobalPoolsAndStaticRules::processNext()
|
||||||
|
{
|
||||||
|
NATCompiler_pix *pix_comp=dynamic_cast<NATCompiler_pix*>(compiler);
|
||||||
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
if (rule->getRuleType()== NATRule::DNAT )
|
||||||
|
{
|
||||||
|
Address *outa=compiler->getFirstODst(rule); assert(outa);
|
||||||
|
Address *insa=compiler->getFirstTDst(rule); assert(insa);
|
||||||
|
|
||||||
|
for (map<int,NATCmd*>::iterator i=pix_comp->nat_commands.begin();
|
||||||
|
i!=pix_comp->nat_commands.end(); ++i)
|
||||||
|
{
|
||||||
|
NATCmd *natcmd=(*i).second;
|
||||||
|
|
||||||
|
if (natcmd->ignore_global) return true;
|
||||||
|
|
||||||
|
/* in this case natcmd->t_addr is interface. Interface creates
|
||||||
|
* single-address global pool, but since it has netmask,
|
||||||
|
* method checkOverlapping would treat it as network. I create
|
||||||
|
* temporary substitution Address object to avoid this .
|
||||||
|
*
|
||||||
|
* If interface is used for a global pool (SNAT rule) and
|
||||||
|
* for a static (DNAT rule), then this is ok even though
|
||||||
|
* such global pool overlaps with such static (added 10/17/03)
|
||||||
|
*
|
||||||
|
* But first I need to check if this interface has dynamic
|
||||||
|
* address, in which case I can not really do this check
|
||||||
|
* at all.
|
||||||
|
*/
|
||||||
|
IPv4 addr;
|
||||||
|
|
||||||
|
Interface *iface=Interface::cast(natcmd->t_addr);
|
||||||
|
if (iface!=NULL && iface->isDyn()) return true;
|
||||||
|
|
||||||
|
if (iface!=NULL && iface->getId()==outa->getId()) return true;
|
||||||
|
|
||||||
|
addr.setAddress(natcmd->t_addr->getAddress());
|
||||||
|
addr.setNetmask(natcmd->t_addr->getNetmask());
|
||||||
|
|
||||||
|
if (natcmd->type== INTERFACE)
|
||||||
|
{
|
||||||
|
addr.setNetmask("255.255.255.255");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( checkOverlapping( addr, outa->getAddress()) ||
|
||||||
|
checkOverlapping( *outa, addr.getAddress()) )
|
||||||
|
compiler->abort("Global pool "
|
||||||
|
+printGlobalPoolAddress(addr)
|
||||||
|
+" from rule "
|
||||||
|
+natcmd->rule_label
|
||||||
|
+" overlaps with static translation address in rule "
|
||||||
|
+rule->getLabel());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NATCompiler_pix::DetectDuplicateNAT::processNext()
|
||||||
|
{
|
||||||
|
NATCompiler_pix *pix_comp=dynamic_cast<NATCompiler_pix*>(compiler);
|
||||||
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
if (rule->getRuleType()== NATRule::SNAT)
|
||||||
|
{
|
||||||
|
NATCmd *natcmd=pix_comp->nat_commands[ rule->getInt("nat_cmd") ];
|
||||||
|
|
||||||
|
if (natcmd->ignore_nat) return true;
|
||||||
|
|
||||||
|
for (map<int,NATCmd*>::iterator i1=pix_comp->nat_commands.begin();
|
||||||
|
i1!=pix_comp->nat_commands.end(); ++i1)
|
||||||
|
{
|
||||||
|
NATCmd *nc=(*i1).second;
|
||||||
|
/* since map nat_commands is sorted by the key, we only have to scan it
|
||||||
|
* until we hit natcmd
|
||||||
|
*/
|
||||||
|
if (nc->ignore_nat) continue;
|
||||||
|
if (natcmd==nc) break;
|
||||||
|
|
||||||
|
Interface *int1=natcmd->t_iface;
|
||||||
|
Interface *int2=nc->t_iface;
|
||||||
|
|
||||||
|
// IPAddress a1=natcmd->o_addr->getAddress();
|
||||||
|
// IPAddress a2=nc->o_addr->getAddress();
|
||||||
|
//
|
||||||
|
// Netmask m1=natcmd->o_addr->getNetmask();
|
||||||
|
// Netmask m2=nc->o_addr->getNetmask();
|
||||||
|
|
||||||
|
if ( int1->getId()==int2->getId() &&
|
||||||
|
natcmd->o_src==nc->o_src &&
|
||||||
|
natcmd->o_dst==nc->o_dst &&
|
||||||
|
*(natcmd->o_srv)==*(nc->o_srv)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
compiler->abort("Duplicate NAT detected: rules "
|
||||||
|
+rule->getLabel()
|
||||||
|
+" and "+nc->rule_label
|
||||||
|
+" : "+natcmd->o_src->getAddress().toString()
|
||||||
|
+"/"+natcmd->o_src->getNetmask().toString()
|
||||||
|
+ " "
|
||||||
|
+ natcmd->o_srv->getProtocolName()
|
||||||
|
+ natcmd->o_srv->getStr("src_range_start")+":"
|
||||||
|
+ natcmd->o_srv->getStr("src_range_end")+":"
|
||||||
|
+ " "
|
||||||
|
+"->"+natcmd->o_dst->getAddress().toString()
|
||||||
|
+"/"+natcmd->o_dst->getNetmask().toString()
|
||||||
|
+ " "
|
||||||
|
+ natcmd->o_srv->getStr("dst_range_start")+"/"
|
||||||
|
+ natcmd->o_srv->getStr("dst_range_end"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NATCompiler_pix::DetectOverlappingStatics::processNext()
|
||||||
|
{
|
||||||
|
NATCompiler_pix *pix_comp=dynamic_cast<NATCompiler_pix*>(compiler);
|
||||||
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
if (rule->getRuleType()== NATRule::DNAT )
|
||||||
|
{
|
||||||
|
StaticCmd *scmd=pix_comp->static_commands[ rule->getInt("sc_cmd") ];
|
||||||
|
|
||||||
|
IPNetwork nn1( scmd->iaddr->getAddress(), scmd->iaddr->getNetmask() );
|
||||||
|
IPNetwork nn2( scmd->oaddr->getAddress(), scmd->oaddr->getNetmask() );
|
||||||
|
|
||||||
|
for (map<int,StaticCmd*>::iterator i1=pix_comp->static_commands.begin();
|
||||||
|
i1!=pix_comp->static_commands.end(); i1++ )
|
||||||
|
{
|
||||||
|
// int scid=i1->first;
|
||||||
|
StaticCmd *sc= i1->second;
|
||||||
|
if (sc->ignore_scmd_and_print_acl) continue;
|
||||||
|
if (sc==scmd) break;
|
||||||
|
|
||||||
|
if (Interface::isA(scmd->oaddr) && Interface::isA(sc->oaddr))
|
||||||
|
{
|
||||||
|
if ( *(sc->osrv) == *(scmd->osrv) &&
|
||||||
|
*(sc->tsrv) == *(scmd->tsrv) &&
|
||||||
|
*(sc->osrc) == *(scmd->osrc) &&
|
||||||
|
sc->oaddr->getId() == scmd->oaddr->getId())
|
||||||
|
compiler->abort("Static NAT rules overlap or are redundant : rules "+
|
||||||
|
sc->rule+" and "+scmd->rule+" : "+
|
||||||
|
"outside address: "+
|
||||||
|
"interface "+Interface::cast(scmd->oaddr)->getLabel()+
|
||||||
|
" inside address: "+
|
||||||
|
scmd->iaddr->getAddress().toString()+"/"+
|
||||||
|
scmd->iaddr->getNetmask().toString());
|
||||||
|
|
||||||
|
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
IPNetwork n1( sc->iaddr->getAddress(), sc->iaddr->getNetmask() );
|
||||||
|
IPNetwork n2( sc->oaddr->getAddress(), sc->oaddr->getNetmask() );
|
||||||
|
|
||||||
|
if ( *(sc->osrv) == *(scmd->osrv) &&
|
||||||
|
*(sc->tsrv) == *(scmd->tsrv) &&
|
||||||
|
*(sc->osrc) == *(scmd->osrc) &&
|
||||||
|
( ! getOverlap(nn1,n1).empty() || ! getOverlap(nn2,n2).empty() ) )
|
||||||
|
compiler->abort("Static NAT rules overlap or are redundant : rules "+
|
||||||
|
sc->rule+" and "+scmd->rule+" : "+
|
||||||
|
"outside address: "+
|
||||||
|
scmd->oaddr->getAddress().toString()+"/"+
|
||||||
|
scmd->oaddr->getNetmask().toString()+
|
||||||
|
" inside address: "+
|
||||||
|
scmd->iaddr->getAddress().toString()+"/"+
|
||||||
|
scmd->iaddr->getNetmask().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void NATCompiler_pix::compile()
|
||||||
|
{
|
||||||
|
cout << " Compiling NAT rules for " << fw->getName() << " ..." << endl << flush;
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
Compiler::compile();
|
||||||
|
|
||||||
|
add( new Begin( "Begin processing"));
|
||||||
|
|
||||||
|
add( new printTotalNumberOfRules());
|
||||||
|
|
||||||
|
if (fw->getOptionsObject()->getBool( "pix_optimize_default_nat"))
|
||||||
|
add (new optimizeDefaultNAT(
|
||||||
|
"optimize commands 'nat (interface) 0.0.0.0 0.0.0.0'"));
|
||||||
|
|
||||||
|
add( new recursiveGroupsInOSrc("check for recursive groups in OSRC"));
|
||||||
|
add( new recursiveGroupsInODst("check for recursive groups in ODST"));
|
||||||
|
add( new recursiveGroupsInOSrv("check for recursive groups in OSRV"));
|
||||||
|
|
||||||
|
add( new recursiveGroupsInTSrc("check for recursive groups in TSRC"));
|
||||||
|
add( new recursiveGroupsInTDst("check for recursive groups in TDST"));
|
||||||
|
add( new recursiveGroupsInTSrv("check for recursive groups in TSRV"));
|
||||||
|
|
||||||
|
|
||||||
|
add( new emptyGroupsInOSrc("check for empty groups in OSRC"));
|
||||||
|
add( new emptyGroupsInODst("check for empty groups in ODST"));
|
||||||
|
add( new emptyGroupsInOSrv("check for empty groups in OSRV"));
|
||||||
|
|
||||||
|
add( new emptyGroupsInTSrc("check for empty groups in TSRC"));
|
||||||
|
add( new emptyGroupsInTDst("check for empty groups in TDST"));
|
||||||
|
add( new emptyGroupsInTSrv("check for empty groups in TSRV"));
|
||||||
|
|
||||||
|
add( new ExpandGroups("expand groups"));
|
||||||
|
add( new eliminateDuplicatesInOSRC("eliminate duplicates in OSRC"));
|
||||||
|
add( new eliminateDuplicatesInODST("eliminate duplicates in ODST"));
|
||||||
|
add( new eliminateDuplicatesInOSRV("eliminate duplicates in OSRV"));
|
||||||
|
|
||||||
|
add( new processMultiAddressObjectsInOSrc(
|
||||||
|
"process MultiAddress objects in OSrc"));
|
||||||
|
add( new processMultiAddressObjectsInODst(
|
||||||
|
"process MultiAddress objects in ODst"));
|
||||||
|
|
||||||
|
add( new ExpandMultipleAddresses("expand multiple addresses"));
|
||||||
|
add( new MACFiltering( "check for MAC address filtering"));
|
||||||
|
add( new ExpandAddressRanges("expand address range objects"));
|
||||||
|
add( new checkForUnnumbered("check for unnumbered interfaces"));
|
||||||
|
|
||||||
|
// add( new ConvertToAtomic("convert to atomic rules"));
|
||||||
|
add( new classifyNATRule("determine NAT rule types"));
|
||||||
|
// add( new fillTranslatedSrv("fill translated service element"));
|
||||||
|
add( new VerifyRules("verify rules" ));
|
||||||
|
add( new ReplaceFirewallObjectsODst("replace fw object in ODst" ));
|
||||||
|
add( new ReplaceFirewallObjectsTSrc("replace fw object in TSrc" ));
|
||||||
|
add( new UseFirewallInterfaces(
|
||||||
|
"replace host objects with firewall's interfaces if the have the same address"));
|
||||||
|
add( new ConvertToAtomic("convert to atomic rules" ));
|
||||||
|
add( new AssignInterface("assign rules to interfaces" ));
|
||||||
|
add( new verifyInterfaces("verify interfaces assignment" ));
|
||||||
|
add( new fillTranslatedSrv("fill translated service element" ));
|
||||||
|
add( new verifyRuleElements(
|
||||||
|
"verify rule elements for static NAT rules"));
|
||||||
|
add( new processNONATRules("process NONAT" ));
|
||||||
|
|
||||||
|
if (fw->getOptionsObject()->getBool("pix_optimize_default_nat"))
|
||||||
|
add (new clearOSrc ("clear OSrc" ));
|
||||||
|
|
||||||
|
add( new createNATCmd ("create NAT commands" ));
|
||||||
|
add( new createStaticCmd ("create static commands" ));
|
||||||
|
add( new mergeNATCmd ("merge NAT commands" ));
|
||||||
|
add( new SuppressDuplicateNONATStatics(
|
||||||
|
"suppress duplicate NONAT statics" ));
|
||||||
|
|
||||||
|
add( new PrintClearCommands( "Clear ACLs" ));
|
||||||
|
|
||||||
|
add( new PrintRule ("generate PIX code" ));
|
||||||
|
add( new storeProcessedRules ("store processed rules" ));
|
||||||
|
add( new simplePrintProgress ());
|
||||||
|
|
||||||
|
bool pix_check_duplicate_nat =
|
||||||
|
fw->getOptionsObject()->getBool("pix_check_duplicate_nat");
|
||||||
|
bool pix_check_overlapping_global_pools =
|
||||||
|
fw->getOptionsObject()->getBool("pix_check_overlapping_global_pools");
|
||||||
|
bool pix_check_overlapping_statics =
|
||||||
|
fw->getOptionsObject()->getBool("pix_check_overlapping_statics");
|
||||||
|
bool pix_check_overlapping_global_statics =
|
||||||
|
fw->getOptionsObject()->getBool("pix_check_overlapping_global_statics");
|
||||||
|
|
||||||
|
if ( pix_check_duplicate_nat ||
|
||||||
|
pix_check_overlapping_global_pools ||
|
||||||
|
pix_check_overlapping_statics ||
|
||||||
|
pix_check_overlapping_global_statics )
|
||||||
|
{
|
||||||
|
add( new createNewCompilerPass(" Detecting nat problems ..."));
|
||||||
|
|
||||||
|
if ( pix_check_duplicate_nat )
|
||||||
|
add( new DetectDuplicateNAT(" Detect duplicate nat entries"));
|
||||||
|
|
||||||
|
if ( pix_check_overlapping_global_pools )
|
||||||
|
add( new DetectGlobalPoolProblems(
|
||||||
|
" Detect global pool overlapping" ));
|
||||||
|
|
||||||
|
if ( pix_check_overlapping_statics )
|
||||||
|
add( new DetectOverlappingStatics(
|
||||||
|
" Detect overlapping statics" ));
|
||||||
|
|
||||||
|
if ( pix_check_overlapping_global_statics )
|
||||||
|
add( new DetectOverlappingGlobalPoolsAndStaticRules(
|
||||||
|
" Detect overlapping global pools and statics" ));
|
||||||
|
|
||||||
|
add( new simplePrintProgress ( ));
|
||||||
|
}
|
||||||
|
|
||||||
|
runRuleProcessors();
|
||||||
|
|
||||||
|
} catch (FWException &ex) {
|
||||||
|
error(ex.toString());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void NATCompiler_pix::regroup()
|
||||||
|
{
|
||||||
|
list<string> commands;
|
||||||
|
map<string,list<string> > script;
|
||||||
|
|
||||||
|
commands.push_back("THE_REST");
|
||||||
|
commands.push_back("access-list ");
|
||||||
|
commands.push_back("global ");
|
||||||
|
commands.push_back("nat ");
|
||||||
|
commands.push_back("static ");
|
||||||
|
|
||||||
|
string acl, agrp, icmp, telnet, ssh;
|
||||||
|
string new_output;
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
|
istringstream in(output.str());
|
||||||
|
|
||||||
|
while (in)
|
||||||
|
{
|
||||||
|
in.getline(buf, 1023, '\n');
|
||||||
|
|
||||||
|
strcat(buf,"\n");
|
||||||
|
|
||||||
|
if (buf[0]=='!') continue;
|
||||||
|
|
||||||
|
string slot="THE_REST";
|
||||||
|
for (list<string>::iterator i=commands.begin(); i!=commands.end(); ++i)
|
||||||
|
{
|
||||||
|
if (strncmp(buf, (*i).c_str(), (*i).size())==0)
|
||||||
|
{
|
||||||
|
slot= *i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
script[slot].push_back(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
output.str("");
|
||||||
|
|
||||||
|
for (list<string>::iterator i=commands.begin(); i!=commands.end(); ++i)
|
||||||
|
{
|
||||||
|
|
||||||
|
for (list<string>::iterator j=script[*i].begin(); j!=script[*i].end(); ++j)
|
||||||
|
output << *j;
|
||||||
|
output << "! \n";
|
||||||
|
output << "! \n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void NATCompiler_pix::epilog()
|
||||||
|
{
|
||||||
|
if ( fw->getOptionsObject()->getBool("pix_regroup_commands"))
|
||||||
|
{
|
||||||
|
cout << " Regrouping commands \n" << flush;
|
||||||
|
regroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,504 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2002 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: NATCompiler_pix.h,v 1.1 2008/03/06 06:48:59 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
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _NATCOMPILER_PIX_HH
|
||||||
|
#define _NATCOMPILER_PIX_HH
|
||||||
|
|
||||||
|
#include "fwcompiler/NATCompiler.h"
|
||||||
|
|
||||||
|
#include "Helper.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
namespace fwcompiler {
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum { UNKNOWN, INTERFACE, SINGLE_ADDRESS, NETWORK_ADDRESS, ADDRESS_RANGE } global_pool_type;
|
||||||
|
typedef enum { NONAT_NAT0, NONAT_STATIC } nonat_types;
|
||||||
|
|
||||||
|
struct NATCmd {
|
||||||
|
|
||||||
|
bool ignore_nat;
|
||||||
|
bool ignore_nat_and_print_acl;
|
||||||
|
bool ignore_global;
|
||||||
|
bool use_nat_0_0;
|
||||||
|
bool outside;
|
||||||
|
std::string rule_label;
|
||||||
|
std::string comment;
|
||||||
|
|
||||||
|
libfwbuilder::Address *o_src; // for "nat" command
|
||||||
|
libfwbuilder::Address *o_dst; // for "nat" command
|
||||||
|
libfwbuilder::Service *o_srv; // for acl in "nat" command for 6.3
|
||||||
|
libfwbuilder::Interface *o_iface; // for "nat" command
|
||||||
|
libfwbuilder::Address *t_addr; // for "global" command
|
||||||
|
libfwbuilder::Interface *t_iface; // for "global" command
|
||||||
|
int nat_id;
|
||||||
|
std::string nat_acl_name;
|
||||||
|
global_pool_type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct StaticCmd {
|
||||||
|
bool ignore_scmd_and_print_acl;
|
||||||
|
std::string acl_name;
|
||||||
|
std::string rule;
|
||||||
|
libfwbuilder::Address *iaddr;
|
||||||
|
libfwbuilder::Address *oaddr;
|
||||||
|
libfwbuilder::Address *osrc;
|
||||||
|
libfwbuilder::Service *osrv;
|
||||||
|
libfwbuilder::Service *tsrv;
|
||||||
|
StaticCmd() { };
|
||||||
|
};
|
||||||
|
|
||||||
|
class NATCompiler_pix : public NATCompiler {
|
||||||
|
|
||||||
|
Helper helper;
|
||||||
|
|
||||||
|
int global_pool_no;
|
||||||
|
std::map<int,NATCmd*> nat_commands;
|
||||||
|
std::map<int,StaticCmd*> static_commands;
|
||||||
|
|
||||||
|
struct nonat {
|
||||||
|
std::string acl_name;
|
||||||
|
libfwbuilder::Interface *i_iface;
|
||||||
|
libfwbuilder::Interface *o_iface;
|
||||||
|
libfwbuilder::Address *src;
|
||||||
|
libfwbuilder::Address *dst;
|
||||||
|
bool last;
|
||||||
|
nonat() { last=false; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// first: rule->getId(), second: nonat object
|
||||||
|
std::map<std::string, nonat> nonat_rules;
|
||||||
|
// first: interface->getId(), second: rule->getId()
|
||||||
|
std::map<std::string,std::string> first_nonat_rule_id;
|
||||||
|
|
||||||
|
libfwbuilder::RuleSet *final_ruleset;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::string debugPrintRule(libfwbuilder::Rule *r);
|
||||||
|
|
||||||
|
/* this is a dictionary of all nat acl names and associated boolean
|
||||||
|
* flag that indicates that corresponding 'clear' command has been
|
||||||
|
* issued. We use this to keep track of all names that are created to
|
||||||
|
* make sure they are unique
|
||||||
|
*/
|
||||||
|
std::map<std::string,int> nat_acl_names;
|
||||||
|
|
||||||
|
std::string getNATACLname(libfwbuilder::Rule *r,int nat_id);
|
||||||
|
std::string getNATACLname(libfwbuilder::Rule *r,std::string suffix);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* verifies correctness of the NAT rules
|
||||||
|
*/
|
||||||
|
DECLARE_NAT_RULE_PROCESSOR(VerifyRules);
|
||||||
|
friend class NATCompiler_pix::VerifyRules;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* using network zone information determine inside and outside
|
||||||
|
* interfaces for the NAT rule
|
||||||
|
*/
|
||||||
|
DECLARE_NAT_RULE_PROCESSOR( AssignInterface );
|
||||||
|
friend class NATCompiler_pix::AssignInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if previous processor assigned the same interface as both
|
||||||
|
* internal and external one for the NAT operation, drop the rule
|
||||||
|
*/
|
||||||
|
DECLARE_NAT_RULE_PROCESSOR( verifyInterfaces );
|
||||||
|
friend class NATCompiler_pix::verifyInterfaces;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* in case of DNAT both odst and tdst should be of the same size:
|
||||||
|
* either both hosts, or both networks of the same size and can not
|
||||||
|
* be address ranges. There are other limitations, too.
|
||||||
|
*/
|
||||||
|
DECLARE_NAT_RULE_PROCESSOR( verifyRuleElements );
|
||||||
|
friend class NATCompiler_pix::verifyRuleElements;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* expands address ranges in OSrc and ODst
|
||||||
|
*/
|
||||||
|
DECLARE_NAT_RULE_PROCESSOR( ExpandAddressRanges );
|
||||||
|
friend class NATCompiler_pix::ExpandAddressRanges;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* in case OSrv is not "any" but TSrv is "original", copy it over
|
||||||
|
*/
|
||||||
|
DECLARE_NAT_RULE_PROCESSOR( fillTranslatedSrv );
|
||||||
|
friend class NATCompiler_pix::fillTranslatedSrv;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* replaces firewall objects in ODst with its external interface(s)
|
||||||
|
*/
|
||||||
|
DECLARE_NAT_RULE_PROCESSOR( ReplaceFirewallObjectsODst );
|
||||||
|
friend class NATCompiler_pix::ReplaceFirewallObjectsODst;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* replaces firewall objects in TSrc with its external interface(s)
|
||||||
|
*/
|
||||||
|
DECLARE_NAT_RULE_PROCESSOR( ReplaceFirewallObjectsTSrc );
|
||||||
|
friend class NATCompiler_pix::ReplaceFirewallObjectsTSrc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* replace host object with firewall's interace if host object
|
||||||
|
* has the same address
|
||||||
|
*/
|
||||||
|
class UseFirewallInterfaces : public NATRuleProcessor
|
||||||
|
{
|
||||||
|
void scanInterfaces(libfwbuilder::RuleElement *rel);
|
||||||
|
public:
|
||||||
|
UseFirewallInterfaces(const std::string &name) : NATRuleProcessor(name){}
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
friend class NATCompiler_pix::UseFirewallInterfaces;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this processor creates ACL for nat 0 rules
|
||||||
|
*/
|
||||||
|
class processNONATRules : public NATRuleProcessor
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
int nonat_no;
|
||||||
|
public:
|
||||||
|
processNONATRules(const std::string &name) : NATRuleProcessor(name){ nonat_no=1; }
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
friend class NATCompiler_pix::processNONATRules;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this processor creates object of class NATCmd if rule is of
|
||||||
|
* type SNAT
|
||||||
|
*/
|
||||||
|
class createNATCmd : public NATRuleProcessor
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
int nat_id_counter;
|
||||||
|
public:
|
||||||
|
createNATCmd(const std::string &name) : NATRuleProcessor(name){ nat_id_counter=1; }
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
friend class NATCompiler_pix::createNATCmd;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates objects of class StaticCmd for all DNAT rules
|
||||||
|
*/
|
||||||
|
class createStaticCmd : public NATRuleProcessor
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
int sc_id_counter;
|
||||||
|
public:
|
||||||
|
createStaticCmd(const std::string &name) : NATRuleProcessor(name){ sc_id_counter=1; }
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
friend class NATCompiler_pix::createStaticCmd;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this processor manipulates list of NATCmd objects so that
|
||||||
|
* to reuse identical "nat" and "global" rules. It also
|
||||||
|
* merges objects of class StaticCmd in DNAT rules to avoid *
|
||||||
|
* duplicate "static" commands
|
||||||
|
*/
|
||||||
|
DECLARE_NAT_RULE_PROCESSOR( mergeNATCmd );
|
||||||
|
friend class NATCompiler_pix::mergeNATCmd;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* takes ID of the original object used in OSrc that has been
|
||||||
|
* stored in storeOriginalOSrcID and compares this object with
|
||||||
|
* network zones of interfaces. If FirewallOption
|
||||||
|
* "pix_optimize_default_nat" is set and original OSrc is the
|
||||||
|
* same as network zone of one of the interfaces, replaces
|
||||||
|
* OSrc in this rule with "Any".
|
||||||
|
*/
|
||||||
|
DECLARE_NAT_RULE_PROCESSOR( optimizeDefaultNAT );
|
||||||
|
friend class NATCompiler_pix::optimizeDefaultNAT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this rule processor uses boolean flag "clear_osrc" set by
|
||||||
|
* optimizeDefaultNAT and removes objects in OSrc if this flag is set.
|
||||||
|
*/
|
||||||
|
DECLARE_NAT_RULE_PROCESSOR( clearOSrc );
|
||||||
|
friend class NATCompiler_pix::clearOSrc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* eliminates duplicate objects in SRC. Uses default comparison
|
||||||
|
* in eliminateDuplicatesInRE which compares IDs
|
||||||
|
*/
|
||||||
|
class eliminateDuplicatesInOSRC : public eliminateDuplicatesInRE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
eliminateDuplicatesInOSRC(const std::string &n) :
|
||||||
|
eliminateDuplicatesInRE(n,libfwbuilder::RuleElementOSrc::TYPENAME) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* eliminates duplicate objects in DST. Uses default comparison
|
||||||
|
* in eliminateDuplicatesInRE which compares IDs
|
||||||
|
*/
|
||||||
|
class eliminateDuplicatesInODST : public eliminateDuplicatesInRE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
eliminateDuplicatesInODST(const std::string &n) :
|
||||||
|
eliminateDuplicatesInRE(n,libfwbuilder::RuleElementODst::TYPENAME) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* eliminates duplicate objects in SRV. Uses default comparison
|
||||||
|
* in eliminateDuplicatesInRE which compares IDs
|
||||||
|
*/
|
||||||
|
class eliminateDuplicatesInOSRV : public eliminateDuplicatesInRE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
eliminateDuplicatesInOSRV(const std::string &n) :
|
||||||
|
eliminateDuplicatesInRE(n,libfwbuilder::RuleElementOSrv::TYPENAME) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Placeholder for MultiAddressRunTime objects that are not
|
||||||
|
* supported for ipf
|
||||||
|
*/
|
||||||
|
class processMultiAddressObjectsInRE : public NATRuleProcessor
|
||||||
|
{
|
||||||
|
std::string re_type;
|
||||||
|
public:
|
||||||
|
processMultiAddressObjectsInRE(const std::string &name,
|
||||||
|
const std::string &t) : NATRuleProcessor(name) { re_type=t; }
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class processMultiAddressObjectsInOSrc : public processMultiAddressObjectsInRE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
processMultiAddressObjectsInOSrc(const std::string &n) :
|
||||||
|
processMultiAddressObjectsInRE(n,libfwbuilder::RuleElementOSrc::TYPENAME) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class processMultiAddressObjectsInODst : public processMultiAddressObjectsInRE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
processMultiAddressObjectsInODst(const std::string &n) :
|
||||||
|
processMultiAddressObjectsInRE(n,libfwbuilder::RuleElementODst::TYPENAME) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this processor accumulates all rules fed to it by previous
|
||||||
|
* processors, then prints PIX commands to clear
|
||||||
|
* access-lists, then feeds all rules to the next
|
||||||
|
* processor. Usually this processor is in chain right
|
||||||
|
* before PrintRules.
|
||||||
|
*
|
||||||
|
* We use this processor to print "clear" commands because
|
||||||
|
* they need to be generated when all access lists have been
|
||||||
|
* created but before they are printed.
|
||||||
|
*/
|
||||||
|
class PrintClearCommands : public NATRuleProcessor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PrintClearCommands(const std::string &n) : NATRuleProcessor(n) {}
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
friend class NATCompiler_pix::PrintClearCommands;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prints single policy rule, assuming all groups have been
|
||||||
|
* expanded, so source, destination and service hold exactly
|
||||||
|
* one object each, and this object is not a group. Negation
|
||||||
|
* should also have been taken care of before this method is
|
||||||
|
* called.
|
||||||
|
*/
|
||||||
|
friend class PrintRule;
|
||||||
|
class PrintRule : public NATRuleProcessor
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
bool init;
|
||||||
|
std::string current_rule_label;
|
||||||
|
std::string _printSrcService(libfwbuilder::Service *srv);
|
||||||
|
std::string _printDstService(libfwbuilder::Service *srv);
|
||||||
|
virtual void _printPort(libfwbuilder::Service *srv);
|
||||||
|
std::string _printAddress(libfwbuilder::Address *a,bool print_netmask);
|
||||||
|
void _printNONAT(libfwbuilder::NATRule *rule);
|
||||||
|
std::string _printConnOptions(libfwbuilder::NATRule *rule);
|
||||||
|
std::map<int,bool> printed_global_pools;
|
||||||
|
public:
|
||||||
|
PrintRule(const std::string &n);
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
friend class NATCompiler_pix::PrintRule;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* detects duplicate nat
|
||||||
|
*/
|
||||||
|
class DetectDuplicateNAT : public NATRuleProcessor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DetectDuplicateNAT(const std::string &n) : NATRuleProcessor(n){}
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
friend class NATCompiler_pix::DetectDuplicateNAT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* base class that has a method that checks for overlapping addresses
|
||||||
|
* taking into account address ranges and other situations
|
||||||
|
*/
|
||||||
|
friend class DetectOverlap;
|
||||||
|
class DetectOverlap : public NATRuleProcessor
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
bool checkOverlapping(const libfwbuilder::Address &a1,
|
||||||
|
const libfwbuilder::IPAddress &a2);
|
||||||
|
std::string printGlobalPoolAddress(const libfwbuilder::Address &pool);
|
||||||
|
public:
|
||||||
|
DetectOverlap(const std::string &n) : NATRuleProcessor(n){}
|
||||||
|
virtual ~DetectOverlap();
|
||||||
|
};
|
||||||
|
friend class NATCompiler_pix::DetectOverlap;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* detects overlapping and some other problems with global pools
|
||||||
|
*/
|
||||||
|
friend class DetectGlobalPoolProblems;
|
||||||
|
class DetectGlobalPoolProblems : public DetectOverlap
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DetectGlobalPoolProblems(const std::string &n) : DetectOverlap(n){}
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
friend class NATCompiler_pix::DetectGlobalPoolProblems;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* detects overlapping global pools and static rules
|
||||||
|
*/
|
||||||
|
friend class DetectOverlappingGlobalPoolsAndStaticRules;
|
||||||
|
class DetectOverlappingGlobalPoolsAndStaticRules : public DetectOverlap
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DetectOverlappingGlobalPoolsAndStaticRules(const std::string &n) : DetectOverlap(n){}
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
friend class NATCompiler_pix::DetectOverlappingGlobalPoolsAndStaticRules;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* suppress identical nonat static (this happens in rules
|
||||||
|
* that request no translation in access from a low security
|
||||||
|
* zone to a high security zone and have group or multiple
|
||||||
|
* objects in OSrc).
|
||||||
|
*/
|
||||||
|
friend class SuppressDuplicateNONATStatics;
|
||||||
|
class SuppressDuplicateNONATStatics : public NATRuleProcessor
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
typedef struct {
|
||||||
|
std::string iface1, iface2;
|
||||||
|
libfwbuilder::IPAddress addr;
|
||||||
|
libfwbuilder::Netmask mask;
|
||||||
|
} nonat_static_parameters;
|
||||||
|
std::deque<nonat_static_parameters> all_nonat_statics;
|
||||||
|
public:
|
||||||
|
SuppressDuplicateNONATStatics(const std::string &n) : NATRuleProcessor(n){}
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
friend class NATCompiler_pix::SuppressDuplicateNONATStatics;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* detects overlapping static
|
||||||
|
*/
|
||||||
|
friend class DetectOverlappingStatics;
|
||||||
|
class DetectOverlappingStatics : public NATRuleProcessor
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
public:
|
||||||
|
DetectOverlappingStatics(const std::string &n) : NATRuleProcessor(n){}
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
friend class NATCompiler_pix::DetectOverlappingStatics;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this processor stores processed NAT rules in final_ruleset
|
||||||
|
*/
|
||||||
|
DECLARE_NAT_RULE_PROCESSOR( storeProcessedRules );
|
||||||
|
friend class NATCompiler_pix::storeProcessedRules;
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual std::string myPlatformName();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
NATCompiler_pix(libfwbuilder::FWObjectDatabase *_db,
|
||||||
|
const std::string &fwname,
|
||||||
|
fwcompiler::OSConfigurator *_oscnf);
|
||||||
|
|
||||||
|
virtual int prolog();
|
||||||
|
virtual void compile();
|
||||||
|
virtual void epilog();
|
||||||
|
|
||||||
|
void regroup();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* scans all rules in combined_ruleset and finds rules (if
|
||||||
|
* any) that define DNAT translation for a combination of
|
||||||
|
* src,dst and srv (that is, src is equival OSrc, srv is equal
|
||||||
|
* OSrv and dst is equal TDst). If such rule could be found,
|
||||||
|
* returns a list of triplets (src,odst,osrv)
|
||||||
|
*/
|
||||||
|
std::list<triplet> findDNATForAddress(
|
||||||
|
libfwbuilder::Address *src,
|
||||||
|
libfwbuilder::Address *dst,
|
||||||
|
libfwbuilder::Service *srv);
|
||||||
|
|
||||||
|
// virtual string atomicRuleToString(libfwbuilder::Rule *r);
|
||||||
|
|
||||||
|
void registerACL(const std::string& acl_name) {
|
||||||
|
setACLFlag(acl_name,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getACLFlag(const std::string& acl_name) {
|
||||||
|
if (nat_acl_names.count(acl_name)!=0)
|
||||||
|
return nat_acl_names[acl_name];
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setACLFlag(const std::string& acl_name, int f) {
|
||||||
|
nat_acl_names[acl_name] = f;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,562 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2002 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: NATCompiler_pix_writers.cpp,v 1.1 2008/03/06 06:48:59 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 "config.h"
|
||||||
|
|
||||||
|
#include "NATCompiler_pix.h"
|
||||||
|
|
||||||
|
#include "fwbuilder/FWObjectDatabase.h"
|
||||||
|
#include "fwbuilder/RuleElement.h"
|
||||||
|
#include "fwbuilder/NAT.h"
|
||||||
|
#include "fwbuilder/AddressRange.h"
|
||||||
|
#include "fwbuilder/ICMPService.h"
|
||||||
|
#include "fwbuilder/TCPService.h"
|
||||||
|
#include "fwbuilder/UDPService.h"
|
||||||
|
#include "fwbuilder/Interface.h"
|
||||||
|
#include "fwbuilder/IPv4.h"
|
||||||
|
#include "fwbuilder/Network.h"
|
||||||
|
#include "fwbuilder/Resources.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
using namespace libfwbuilder;
|
||||||
|
using namespace fwcompiler;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
bool NATCompiler_pix::PrintClearCommands::processNext()
|
||||||
|
{
|
||||||
|
NATCompiler_pix *pix_comp=dynamic_cast<NATCompiler_pix*>(compiler);
|
||||||
|
string version = compiler->fw->getStr("version");
|
||||||
|
string platform = compiler->fw->getStr("platform");
|
||||||
|
|
||||||
|
slurp();
|
||||||
|
if (tmp_queue.size()==0) return false;
|
||||||
|
|
||||||
|
compiler->output << endl;
|
||||||
|
|
||||||
|
if ( !compiler->fw->getOptionsObject()->getBool("pix_acl_no_clear") )
|
||||||
|
{
|
||||||
|
compiler->output << Resources::platform_res[platform]->getResourceStr(
|
||||||
|
string("/FWBuilderResources/Target/options/")+
|
||||||
|
"version_"+version+"/pix_commands/clear_xlate") << endl;
|
||||||
|
compiler->output << Resources::platform_res[platform]->getResourceStr(
|
||||||
|
string("/FWBuilderResources/Target/options/")+
|
||||||
|
"version_"+version+"/pix_commands/clear_static") << endl;
|
||||||
|
compiler->output << Resources::platform_res[platform]->getResourceStr(
|
||||||
|
string("/FWBuilderResources/Target/options/")+
|
||||||
|
"version_"+version+"/pix_commands/clear_global") << endl;
|
||||||
|
compiler->output << Resources::platform_res[platform]->getResourceStr(
|
||||||
|
string("/FWBuilderResources/Target/options/")+
|
||||||
|
"version_"+version+"/pix_commands/clear_nat") << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
string NATCompiler_pix::PrintRule::_printAddress(Address *a,bool print_netmask)
|
||||||
|
{
|
||||||
|
string addr=a->getAddress().toString();
|
||||||
|
string mask=a->getNetmask().toString();
|
||||||
|
if (addr=="0.0.0.0" && mask=="0.0.0.0") return "any";
|
||||||
|
// if (addr=="0.0.0.0") addr="0";
|
||||||
|
// if (mask=="0.0.0.0") mask="0";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the object 'a' is a Host or a IPv4 (that is, it defines only
|
||||||
|
* a single IP address) but its netmask is not 255.255.255.255, PIX will
|
||||||
|
* issue an error "address,mask doesn't pair".
|
||||||
|
*
|
||||||
|
* I am not sure if it is appropriate to just fix this for the user,
|
||||||
|
* may be I should issue a warning or even abort.
|
||||||
|
*/
|
||||||
|
if (Host::isA(a) || IPv4::isA(a)) mask="255.255.255.255";
|
||||||
|
|
||||||
|
if (mask=="255.255.255.255") { addr="host "+addr; mask=""; }
|
||||||
|
if (print_netmask) return addr+" "+mask;
|
||||||
|
else return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NATCompiler_pix::PrintRule::_printNONAT(NATRule *rule)
|
||||||
|
{
|
||||||
|
Helper helper(compiler);
|
||||||
|
NATCompiler_pix *pix_comp=dynamic_cast<NATCompiler_pix*>(compiler);
|
||||||
|
|
||||||
|
string platform = compiler->fw->getStr("platform");
|
||||||
|
string version = compiler->fw->getStr("version");
|
||||||
|
string clearACLcmd = Resources::platform_res[platform]->getResourceStr(
|
||||||
|
string("/FWBuilderResources/Target/options/")+
|
||||||
|
"version_"+version+"/pix_commands/clear_acl");
|
||||||
|
|
||||||
|
switch (rule->getInt("nonat_type"))
|
||||||
|
{
|
||||||
|
case NONAT_NAT0:
|
||||||
|
{
|
||||||
|
nonat n0=pix_comp->nonat_rules[rule->getId()];
|
||||||
|
Interface *iface1=n0.i_iface;
|
||||||
|
// Interface *iface2=n0.o_iface;
|
||||||
|
|
||||||
|
if (rule->getBool("use_nat_0_0"))
|
||||||
|
{
|
||||||
|
/* old, < 6.3 */
|
||||||
|
compiler->output << "nat (" << iface1->getLabel() << ") 0 0 0";
|
||||||
|
compiler->output << endl;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
/* new, >=6.3 */
|
||||||
|
|
||||||
|
compiler->output << endl;
|
||||||
|
|
||||||
|
if (pix_comp->getACLFlag(n0.acl_name)==0 &&
|
||||||
|
compiler->fw->getOptionsObject()->getBool("pix_acl_substitution"))
|
||||||
|
{
|
||||||
|
compiler->output << clearACLcmd <<" " << n0.acl_name << endl;
|
||||||
|
pix_comp->setACLFlag(n0.acl_name,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
compiler->output << "access-list "
|
||||||
|
<< n0.acl_name
|
||||||
|
<< " permit ip "
|
||||||
|
<< _printAddress(n0.src,true)
|
||||||
|
<< " "
|
||||||
|
<< _printAddress(n0.dst,true)
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
if ( pix_comp->first_nonat_rule_id[iface1->getId()]==rule->getId() )
|
||||||
|
{
|
||||||
|
if (compiler->fw->getStr("platform")=="fwsm" &&
|
||||||
|
compiler->fw->getOptionsObject()->getBool("pix_use_manual_commit") )
|
||||||
|
{
|
||||||
|
compiler->output << "access-list commit" << endl;
|
||||||
|
compiler->output << endl;
|
||||||
|
}
|
||||||
|
compiler->output << "nat ("
|
||||||
|
<< iface1->getLabel()
|
||||||
|
<< ") 0 access-list "
|
||||||
|
<< n0.acl_name
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NONAT_STATIC:
|
||||||
|
{
|
||||||
|
Address *osrc=compiler->getFirstOSrc(rule); assert(osrc);
|
||||||
|
Address *odst=compiler->getFirstODst(rule); assert(odst);
|
||||||
|
|
||||||
|
Interface *osrc_iface=compiler->getCachedFwInterface( helper.findInterfaceByNetzone(osrc ) );
|
||||||
|
Interface *odst_iface=compiler->getCachedFwInterface( helper.findInterfaceByNetzone(odst ) );
|
||||||
|
|
||||||
|
string addr=odst->getAddress().toString();
|
||||||
|
string mask;
|
||||||
|
if (Network::isA(odst)) mask=odst->getNetmask().toString();
|
||||||
|
else mask="255.255.255.255";
|
||||||
|
|
||||||
|
compiler->output << "static ("
|
||||||
|
<< odst_iface->getLabel() << ","
|
||||||
|
<< osrc_iface->getLabel() << ") "
|
||||||
|
<< addr << " " << addr
|
||||||
|
<< " netmask " << mask
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NATCompiler_pix::PrintRule::PrintRule(const std::string &name) : NATRuleProcessor(name)
|
||||||
|
{
|
||||||
|
init=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we verify that port ranges are not used in verifyRuleElements
|
||||||
|
*/
|
||||||
|
void NATCompiler_pix::PrintRule::_printPort(Service *srv)
|
||||||
|
{
|
||||||
|
if (TCPService::isA(srv) || UDPService::isA(srv))
|
||||||
|
{
|
||||||
|
int drs=srv->getInt("dst_range_start");
|
||||||
|
|
||||||
|
if (drs!=0) compiler->output << drs << " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string NATCompiler_pix::PrintRule::_printSrcService(Service *srv)
|
||||||
|
{
|
||||||
|
ostringstream str;
|
||||||
|
|
||||||
|
if (TCPService::isA(srv) || UDPService::isA(srv))
|
||||||
|
{
|
||||||
|
int rs=srv->getInt("src_range_start");
|
||||||
|
int re=srv->getInt("src_range_end");
|
||||||
|
|
||||||
|
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 NATCompiler_pix::PrintRule::_printDstService(Service *srv)
|
||||||
|
{
|
||||||
|
ostringstream str;
|
||||||
|
|
||||||
|
if (TCPService::isA(srv) || UDPService::isA(srv)) {
|
||||||
|
int rs=srv->getInt("dst_range_start");
|
||||||
|
int re=srv->getInt("dst_range_end");
|
||||||
|
|
||||||
|
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 (ICMPService::isA(srv) && srv->getInt("type")!=-1)
|
||||||
|
str << srv->getStr("type") << " ";
|
||||||
|
return str.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
string NATCompiler_pix::PrintRule::_printConnOptions(NATRule *rule)
|
||||||
|
{
|
||||||
|
if (rule==NULL) return "";
|
||||||
|
|
||||||
|
ostringstream ostr;
|
||||||
|
|
||||||
|
int max_conns=compiler->fw->getOptionsObject()->getInt("pix_max_conns");
|
||||||
|
int emb_limit=compiler->fw->getOptionsObject()->getInt("pix_emb_limit");
|
||||||
|
|
||||||
|
if (max_conns<0) max_conns=0;
|
||||||
|
if (emb_limit<0) emb_limit=0;
|
||||||
|
|
||||||
|
// we only support tcp connection options at this time
|
||||||
|
// however PIX 7.0 (7.2?) also supports udp conn limit
|
||||||
|
//
|
||||||
|
// Note that keyword 'tcp' here is only valid in 7.x
|
||||||
|
if (libfwbuilder::XMLTools::version_compare(
|
||||||
|
compiler->fw->getStr("version"),"7.0")>=0) ostr << "tcp ";
|
||||||
|
|
||||||
|
ostr << max_conns << " " << emb_limit;
|
||||||
|
return ostr.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NATCompiler_pix::PrintRule::processNext()
|
||||||
|
{
|
||||||
|
NATCompiler_pix *pix_comp=dynamic_cast<NATCompiler_pix*>(compiler);
|
||||||
|
|
||||||
|
string platform = compiler->fw->getStr("platform");
|
||||||
|
string version = compiler->fw->getStr("version");
|
||||||
|
string clearACLcmd = Resources::platform_res[platform]->getResourceStr(
|
||||||
|
string("/FWBuilderResources/Target/options/")+
|
||||||
|
"version_"+version+"/pix_commands/clear_acl");
|
||||||
|
|
||||||
|
NATRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
if ( compiler->fw->getOptionsObject()->getBool("pix_include_comments") )
|
||||||
|
{
|
||||||
|
string rl=rule->getLabel();
|
||||||
|
if (rl!=current_rule_label)
|
||||||
|
{
|
||||||
|
compiler->output << "! " << endl;
|
||||||
|
compiler->output << "! Rule " << rl << endl;
|
||||||
|
|
||||||
|
string comm=rule->getComment();
|
||||||
|
string::size_type c1,c2;
|
||||||
|
c1=0;
|
||||||
|
while ( (c2=comm.find('\n',c1))!=string::npos ) {
|
||||||
|
compiler->output << "! " << comm.substr(c1,c2-c1) << endl;
|
||||||
|
c1=c2+1;
|
||||||
|
}
|
||||||
|
compiler->output << "! " << comm.substr(c1) << endl;
|
||||||
|
compiler->output << "! " << endl;
|
||||||
|
|
||||||
|
current_rule_label=rl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Address *osrc=compiler->getFirstOSrc(rule); assert(osrc);
|
||||||
|
Address *odst=compiler->getFirstODst(rule); assert(odst);
|
||||||
|
Service *osrv=compiler->getFirstOSrv(rule); assert(osrv);
|
||||||
|
|
||||||
|
Address *tsrc=compiler->getFirstTSrc(rule); assert(tsrc);
|
||||||
|
Address *tdst=compiler->getFirstTDst(rule); assert(tdst);
|
||||||
|
Service *tsrv=compiler->getFirstTSrv(rule); assert(tsrv);
|
||||||
|
|
||||||
|
|
||||||
|
Interface *iface_orig = compiler->getCachedFwInterface( rule->getStr("nat_iface_orig") );
|
||||||
|
Interface *iface_trn = compiler->getCachedFwInterface( rule->getStr("nat_iface_trn" ) );
|
||||||
|
|
||||||
|
switch (rule->getRuleType())
|
||||||
|
{
|
||||||
|
case NATRule::NONAT:
|
||||||
|
_printNONAT(rule);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NATRule::SNAT:
|
||||||
|
{
|
||||||
|
NATCmd *natcmd=pix_comp->nat_commands[ rule->getInt("nat_cmd") ];
|
||||||
|
|
||||||
|
if ( ! natcmd->ignore_global)
|
||||||
|
{
|
||||||
|
compiler->output <<
|
||||||
|
"global (" << natcmd->t_iface->getLabel() << ") "
|
||||||
|
<< natcmd->nat_id;
|
||||||
|
|
||||||
|
switch (natcmd->type)
|
||||||
|
{
|
||||||
|
case INTERFACE:
|
||||||
|
compiler->output << " interface" << endl;
|
||||||
|
break;
|
||||||
|
case SINGLE_ADDRESS:
|
||||||
|
compiler->output << " "
|
||||||
|
<< natcmd->t_addr->getAddress().toString()
|
||||||
|
<< endl;
|
||||||
|
break;
|
||||||
|
case NETWORK_ADDRESS:
|
||||||
|
compiler->output << " "
|
||||||
|
<< natcmd->t_addr->getAddress().toString()
|
||||||
|
<< " netmask "
|
||||||
|
<< natcmd->t_addr->getNetmask().toString()
|
||||||
|
<< endl;
|
||||||
|
break;
|
||||||
|
case ADDRESS_RANGE:
|
||||||
|
{
|
||||||
|
AddressRange *ar=AddressRange::cast(natcmd->t_addr);
|
||||||
|
compiler->output << " "
|
||||||
|
<< ar->getRangeStart().toString()
|
||||||
|
<< "-"
|
||||||
|
<< ar->getRangeEnd().toString()
|
||||||
|
<< " netmask "
|
||||||
|
<< natcmd->t_iface->getNetmask().toString()
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: ; // TODO: should actually be always_assert
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( natcmd->ignore_nat)
|
||||||
|
{
|
||||||
|
compiler->output <<"! " << natcmd->comment << endl;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (rule->getBool("use_nat_0_0") ||
|
||||||
|
libfwbuilder::XMLTools::version_compare(compiler->fw->getStr("version"),"6.3")<0)
|
||||||
|
{
|
||||||
|
/* old, < 6.3 */
|
||||||
|
compiler->output << "nat (" << natcmd->o_iface->getLabel() << ") "
|
||||||
|
<< natcmd->nat_id
|
||||||
|
<< " "
|
||||||
|
<< natcmd->o_src->getAddress().toString() << " "
|
||||||
|
<< natcmd->o_src->getNetmask().toString();
|
||||||
|
if (natcmd->outside) compiler->output << " outside";
|
||||||
|
else compiler->output << " " << _printConnOptions(rule);
|
||||||
|
compiler->output << endl;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
/* new, >=6.3 */
|
||||||
|
if (pix_comp->getACLFlag(natcmd->nat_acl_name)==0 &&
|
||||||
|
compiler->fw->getOptionsObject()->getBool("pix_acl_substitution"))
|
||||||
|
{
|
||||||
|
compiler->output << clearACLcmd << " "
|
||||||
|
<< natcmd->nat_acl_name
|
||||||
|
<< endl;
|
||||||
|
pix_comp->setACLFlag(natcmd->nat_acl_name,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
compiler->output << "access-list "
|
||||||
|
<< natcmd->nat_acl_name
|
||||||
|
<< " permit ";
|
||||||
|
compiler->output << osrv->getProtocolName();
|
||||||
|
compiler->output << " ";
|
||||||
|
compiler->output << _printAddress(osrc,true);
|
||||||
|
compiler->output << " ";
|
||||||
|
compiler->output << _printSrcService( osrv );
|
||||||
|
compiler->output << " ";
|
||||||
|
compiler->output << _printAddress(odst,true);
|
||||||
|
compiler->output << " ";
|
||||||
|
compiler->output << _printDstService( osrv );
|
||||||
|
compiler->output << endl;
|
||||||
|
|
||||||
|
if (!natcmd->ignore_nat_and_print_acl)
|
||||||
|
{
|
||||||
|
if (compiler->fw->getStr("platform")=="fwsm" &&
|
||||||
|
compiler->fw->getOptionsObject()->getBool("pix_use_manual_commit") )
|
||||||
|
{
|
||||||
|
compiler->output << "access-list commit" << endl;
|
||||||
|
compiler->output << endl;
|
||||||
|
}
|
||||||
|
compiler->output << "nat (" << natcmd->o_iface->getLabel() << ") "
|
||||||
|
<< natcmd->nat_id
|
||||||
|
<< " access-list "
|
||||||
|
<< natcmd->nat_acl_name;
|
||||||
|
if (natcmd->outside) compiler->output << " outside";
|
||||||
|
else compiler->output << " " << _printConnOptions(rule);
|
||||||
|
compiler->output << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case NATRule::DNAT:
|
||||||
|
{
|
||||||
|
StaticCmd *scmd=pix_comp->static_commands[ rule->getInt("sc_cmd") ];
|
||||||
|
|
||||||
|
IPAddress outa=scmd->oaddr->getAddress();
|
||||||
|
Netmask outm=scmd->oaddr->getNetmask();
|
||||||
|
IPAddress insa=scmd->iaddr->getAddress();
|
||||||
|
/*
|
||||||
|
* we verify that odst and tdst have the same size in verifyRuleElements,
|
||||||
|
* so we can rely on that now.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (libfwbuilder::XMLTools::version_compare(compiler->fw->getStr("version"),"6.3")<0)
|
||||||
|
{
|
||||||
|
/* old, < 6.3 */
|
||||||
|
|
||||||
|
compiler->output << "static ("
|
||||||
|
<< iface_trn->getLabel()
|
||||||
|
<< ","
|
||||||
|
<< iface_orig->getLabel()
|
||||||
|
<< ") " ;
|
||||||
|
|
||||||
|
bool use_ports=false;
|
||||||
|
|
||||||
|
if (TCPService::cast(osrv)) { use_ports=true; compiler->output << "tcp "; }
|
||||||
|
if (UDPService::cast(osrv)) { use_ports=true; compiler->output << "udp "; }
|
||||||
|
|
||||||
|
if (Interface::cast(scmd->oaddr)!=NULL)
|
||||||
|
{
|
||||||
|
compiler->output << "interface ";
|
||||||
|
if (use_ports) _printPort(scmd->osrv);
|
||||||
|
|
||||||
|
compiler->output << insa.toString() << " ";
|
||||||
|
if (use_ports) _printPort(scmd->tsrv);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
compiler->output << outa.toString() << " ";
|
||||||
|
if (use_ports) _printPort(scmd->osrv);
|
||||||
|
|
||||||
|
compiler->output << insa.toString() << " ";
|
||||||
|
if (use_ports) _printPort(scmd->tsrv);
|
||||||
|
|
||||||
|
compiler->output << " netmask " << outm.toString();
|
||||||
|
}
|
||||||
|
compiler->output << " " << _printConnOptions(rule) << endl;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
/* new, >=6.3 */
|
||||||
|
|
||||||
|
if (pix_comp->getACLFlag(scmd->acl_name)==0 &&
|
||||||
|
compiler->fw->getOptionsObject()->getBool("pix_acl_substitution"))
|
||||||
|
{
|
||||||
|
compiler->output << clearACLcmd << " "
|
||||||
|
<< scmd->acl_name
|
||||||
|
<< endl;
|
||||||
|
pix_comp->setACLFlag(scmd->acl_name,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
compiler->output << "access-list "
|
||||||
|
<< scmd->acl_name
|
||||||
|
<< " permit ";
|
||||||
|
/*
|
||||||
|
* This acl does not make any sense if treated as a regular access
|
||||||
|
* list. I just follow example from
|
||||||
|
* http://www.cisco.com/en/US/products/sw/secursw/ps2120/products_configuration_guide_chapter09186a0080172786.html#1113601
|
||||||
|
*/
|
||||||
|
compiler->output << scmd->osrv->getProtocolName();
|
||||||
|
compiler->output << " ";
|
||||||
|
compiler->output << _printAddress(scmd->iaddr,true);
|
||||||
|
compiler->output << " ";
|
||||||
|
compiler->output << _printDstService( scmd->tsrv );
|
||||||
|
compiler->output << " ";
|
||||||
|
compiler->output << _printAddress(scmd->osrc,true);
|
||||||
|
compiler->output << " ";
|
||||||
|
compiler->output << _printSrcService( scmd->osrv );
|
||||||
|
compiler->output << endl;
|
||||||
|
|
||||||
|
if (!scmd->ignore_scmd_and_print_acl)
|
||||||
|
{
|
||||||
|
if (compiler->fw->getStr("platform")=="fwsm" &&
|
||||||
|
compiler->fw->getOptionsObject()->getBool("pix_use_manual_commit") )
|
||||||
|
{
|
||||||
|
compiler->output << "access-list commit" << endl;
|
||||||
|
compiler->output << endl;
|
||||||
|
}
|
||||||
|
compiler->output << "static ("
|
||||||
|
<< iface_trn->getLabel()
|
||||||
|
<< ","
|
||||||
|
<< iface_orig->getLabel()
|
||||||
|
<< ") " ;
|
||||||
|
|
||||||
|
bool use_ports=false;
|
||||||
|
if (TCPService::cast(scmd->osrv)) { use_ports=true; compiler->output << "tcp "; }
|
||||||
|
if (UDPService::cast(scmd->osrv)) { use_ports=true; compiler->output << "udp "; }
|
||||||
|
|
||||||
|
if (Interface::cast(scmd->oaddr)!=NULL) compiler->output << "interface ";
|
||||||
|
else compiler->output << outa.toString() << " ";
|
||||||
|
if (use_ports) _printPort(scmd->osrv);
|
||||||
|
compiler->output << " ";
|
||||||
|
|
||||||
|
compiler->output << "access-list "
|
||||||
|
<< scmd->acl_name
|
||||||
|
<< " " << _printConnOptions(rule) << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: ; // TODO: should actually be always_assert
|
||||||
|
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,535 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2002 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: OSConfigurator_pix_os.cpp,v 1.1 2008/03/06 06:49:00 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 "OSConfigurator_pix_os.h"
|
||||||
|
#include "Helper.h"
|
||||||
|
#include "fwbuilder/Resources.h"
|
||||||
|
|
||||||
|
#include "fwbuilder/Firewall.h"
|
||||||
|
#include "fwbuilder/FWOptions.h"
|
||||||
|
#include "fwbuilder/Interface.h"
|
||||||
|
#include "fwbuilder/Management.h"
|
||||||
|
#include "fwbuilder/Resources.h"
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace libfwbuilder;
|
||||||
|
using namespace fwcompiler;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
string OSConfigurator_pix_os::myPlatformName() { return "pix_os"; }
|
||||||
|
|
||||||
|
int OSConfigurator_pix_os::prolog()
|
||||||
|
{
|
||||||
|
string host_os = fw->getStr("host_OS");
|
||||||
|
|
||||||
|
if (host_os!="pix_os" && host_os!="fwsm_os")
|
||||||
|
abort("Unsupported OS " + host_os );
|
||||||
|
|
||||||
|
return Compiler::prolog();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OSConfigurator_pix_os::processFirewallOptions()
|
||||||
|
{
|
||||||
|
// FWOptions* options=fw->getOptionsObject();
|
||||||
|
string s;
|
||||||
|
// int i;
|
||||||
|
string version = fw->getStr("version");
|
||||||
|
string platform = fw->getStr("platform");
|
||||||
|
|
||||||
|
|
||||||
|
if ( fw->getOptionsObject()->getBool("pix_set_host_name") )
|
||||||
|
{
|
||||||
|
output << "hostname " << fw->getName() << endl;
|
||||||
|
output << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
output << _printNameif();
|
||||||
|
output << endl;
|
||||||
|
output << _printIPAddress();
|
||||||
|
output << endl;
|
||||||
|
output << _printLogging();
|
||||||
|
output << endl;
|
||||||
|
output << _printTimeouts();
|
||||||
|
output << endl;
|
||||||
|
output << _printSNMP();
|
||||||
|
output << endl;
|
||||||
|
output << _printNTP();
|
||||||
|
output << endl;
|
||||||
|
output << _printSysopt();
|
||||||
|
output << endl;
|
||||||
|
output << getProtocolInspectionCommands();
|
||||||
|
output << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
string OSConfigurator_pix_os::_printNameif()
|
||||||
|
{
|
||||||
|
ostringstream res;
|
||||||
|
string version = fw->getStr("version");
|
||||||
|
string platform = fw->getStr("platform");
|
||||||
|
string::size_type n;
|
||||||
|
|
||||||
|
list<FWObject*> l2=fw->getByType(Interface::TYPENAME);
|
||||||
|
for (list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i)
|
||||||
|
{
|
||||||
|
Interface *iface=dynamic_cast<Interface*>(*i);
|
||||||
|
assert(iface);
|
||||||
|
|
||||||
|
string nameifCmd = Resources::platform_res[platform]->getResourceStr(
|
||||||
|
string("/FWBuilderResources/Target/options/version_")+
|
||||||
|
version+"/pix_commands/nameif");
|
||||||
|
|
||||||
|
if ((n = nameifCmd.find("%il"))!=string::npos)
|
||||||
|
nameifCmd.replace(n,3,iface->getLabel());
|
||||||
|
if ((n = nameifCmd.find("%in"))!=string::npos)
|
||||||
|
nameifCmd.replace(n,3,iface->getName());
|
||||||
|
if ((n = nameifCmd.find("%sl"))!=string::npos)
|
||||||
|
{
|
||||||
|
ostringstream sls;
|
||||||
|
sls << iface->getSecurityLevel();
|
||||||
|
nameifCmd.replace(n,3,sls.str());
|
||||||
|
}
|
||||||
|
res << nameifCmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
res << endl;
|
||||||
|
|
||||||
|
return res.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
string OSConfigurator_pix_os::_printIPAddress()
|
||||||
|
{
|
||||||
|
ostringstream res;
|
||||||
|
string version = fw->getStr("version");
|
||||||
|
string platform = fw->getStr("platform");
|
||||||
|
string setAddrCmd;
|
||||||
|
string::size_type n;
|
||||||
|
|
||||||
|
if ( fw->getOptionsObject()->getBool("pix_ip_address") )
|
||||||
|
{
|
||||||
|
list<FWObject*> l2=fw->getByType(Interface::TYPENAME);
|
||||||
|
for (list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i)
|
||||||
|
{
|
||||||
|
Interface *iface=dynamic_cast<Interface*>(*i);
|
||||||
|
assert(iface);
|
||||||
|
if (iface->isDyn())
|
||||||
|
{
|
||||||
|
setAddrCmd = Resources::platform_res[platform]->getResourceStr(
|
||||||
|
string("/FWBuilderResources/Target/options/version_")+
|
||||||
|
version+"/pix_commands/ip_addr_dyn");
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
setAddrCmd = Resources::platform_res[platform]->getResourceStr(
|
||||||
|
string("/FWBuilderResources/Target/options/version_")+
|
||||||
|
version+"/pix_commands/ip_addr_static");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((n = setAddrCmd.find("%il"))!=string::npos)
|
||||||
|
setAddrCmd.replace(n,3,iface->getLabel());
|
||||||
|
if ((n = setAddrCmd.find("%in"))!=string::npos)
|
||||||
|
setAddrCmd.replace(n,3,iface->getName());
|
||||||
|
if ((n = setAddrCmd.find("%a"))!=string::npos)
|
||||||
|
setAddrCmd.replace(n,2,iface->getAddress().toString());
|
||||||
|
if ((n = setAddrCmd.find("%n"))!=string::npos)
|
||||||
|
setAddrCmd.replace(n,2,iface->getNetmask().toString());
|
||||||
|
|
||||||
|
res << setAddrCmd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res << endl;
|
||||||
|
|
||||||
|
return res.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string OSConfigurator_pix_os::_printLogging()
|
||||||
|
{
|
||||||
|
Helper helper(this);
|
||||||
|
|
||||||
|
ostringstream str;
|
||||||
|
bool logging_on=false;
|
||||||
|
|
||||||
|
string syslog_host = fw->getOptionsObject()->getStr("pix_syslog_host");
|
||||||
|
int syslog_queue_size=fw->getOptionsObject()->getInt("pix_syslog_queue_size");
|
||||||
|
string syslog_facility= fw->getOptionsObject()->getStr("pix_syslog_facility");
|
||||||
|
string trap_level= fw->getOptionsObject()->getStr("pix_logging_trap_level");
|
||||||
|
|
||||||
|
bool buffered= fw->getOptionsObject()->getBool("pix_logging_buffered");
|
||||||
|
string buffered_level= fw->getOptionsObject()->getStr("pix_logging_buffered_level");
|
||||||
|
|
||||||
|
bool console= fw->getOptionsObject()->getBool("pix_logging_console");
|
||||||
|
string console_level= fw->getOptionsObject()->getStr("pix_logging_console_level");
|
||||||
|
|
||||||
|
bool timestamp= fw->getOptionsObject()->getBool("pix_logging_timestamp");
|
||||||
|
|
||||||
|
if ( ! syslog_host.empty() )
|
||||||
|
{
|
||||||
|
string iface_id=helper.findInterfaceByNetzone(IPAddress(syslog_host));
|
||||||
|
if (iface_id.empty()) abort("Log server "+syslog_host+" does not belong to any known network zone");
|
||||||
|
Interface *syslog_iface = getCachedFwInterface(iface_id);
|
||||||
|
|
||||||
|
str << endl;
|
||||||
|
|
||||||
|
str << "logging host "
|
||||||
|
<< syslog_iface->getLabel()
|
||||||
|
<< " " << syslog_host;
|
||||||
|
|
||||||
|
if ( fw->getOptionsObject()->getBool("pix_emblem_log_format") )
|
||||||
|
str << " format emblem ";
|
||||||
|
|
||||||
|
str << endl;
|
||||||
|
|
||||||
|
str << "logging queue "
|
||||||
|
<< syslog_queue_size << endl;
|
||||||
|
|
||||||
|
if ( ! syslog_facility.empty() )
|
||||||
|
str << "logging facility " << syslog_facility << endl;
|
||||||
|
|
||||||
|
if ( ! trap_level.empty() )
|
||||||
|
str << "logging trap " << trap_level << endl;
|
||||||
|
|
||||||
|
logging_on=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! buffered ) str << "no logging buffered" << endl;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
str << "logging buffered " << buffered_level << endl;
|
||||||
|
logging_on=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! console ) str << "no logging console" << endl;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
str << "logging console " << console_level << endl;
|
||||||
|
logging_on=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! timestamp ) str << "no ";
|
||||||
|
str << "logging timestamp" << endl;
|
||||||
|
|
||||||
|
if ( ! logging_on) str << "no ";
|
||||||
|
str << "logging on" << endl;
|
||||||
|
|
||||||
|
string s=fw->getOptionsObject()->getStr("pix_syslog_device_id_opt");
|
||||||
|
string v=fw->getOptionsObject()->getStr("pix_syslog_device_id_val");
|
||||||
|
if (s=="hostname") str << "logging device-id hostname" << endl;
|
||||||
|
if (s=="interface") str << "logging device-id ipaddress " << v << endl;
|
||||||
|
if (s=="string") str << "logging device-id string " << v << endl;
|
||||||
|
|
||||||
|
str << endl;
|
||||||
|
|
||||||
|
return str.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
string OSConfigurator_pix_os::_printSNMPServer(const std::string &srv,int poll_trap)
|
||||||
|
{
|
||||||
|
Helper helper(this);
|
||||||
|
|
||||||
|
ostringstream str;
|
||||||
|
|
||||||
|
string iface_id=helper.findInterfaceByNetzone( IPAddress(srv) );
|
||||||
|
if (iface_id.empty())
|
||||||
|
abort(string("SNMP server ")+srv+" does not belong to any known network zone");
|
||||||
|
Interface *snmp_iface = getCachedFwInterface(iface_id);
|
||||||
|
str << "snmp-server host " << snmp_iface->getLabel() << " " << srv;
|
||||||
|
switch (poll_trap) {
|
||||||
|
case 1: str << " poll" << endl; break;
|
||||||
|
case 2: str << " trap" << endl; break;
|
||||||
|
default: str << endl; break;
|
||||||
|
}
|
||||||
|
return str.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
string OSConfigurator_pix_os::_printSNMP()
|
||||||
|
{
|
||||||
|
ostringstream str;
|
||||||
|
string version = fw->getStr("version");
|
||||||
|
string platform = fw->getStr("platform");
|
||||||
|
|
||||||
|
bool set_communities=fw->getOptionsObject()->getBool("pix_set_communities_from_object_data");
|
||||||
|
bool set_sysinfo= fw->getOptionsObject()->getBool("pix_set_sysinfo_from_object_data" );
|
||||||
|
bool enable_traps= fw->getOptionsObject()->getBool("pix_enable_snmp_traps");
|
||||||
|
|
||||||
|
string clearSNMPcmd = Resources::platform_res[platform]->getResourceStr(
|
||||||
|
string("/FWBuilderResources/Target/options/version_")+
|
||||||
|
version+"/pix_commands/clear_snmp");
|
||||||
|
|
||||||
|
if ( !fw->getOptionsObject()->getBool("pix_acl_no_clear") )
|
||||||
|
str << clearSNMPcmd << endl;
|
||||||
|
|
||||||
|
if ( fw->getOptionsObject()->getBool("pix_disable_snmp_agent") )
|
||||||
|
{
|
||||||
|
str << "no snmp-server " << endl;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
|
||||||
|
if (set_communities) {
|
||||||
|
string read_c=fw->getManagementObject()->getSNMPManagement()->getReadCommunity();
|
||||||
|
str << endl;
|
||||||
|
str << "snmp-server community " << read_c << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set_sysinfo) {
|
||||||
|
string location=fw->getOptionsObject()->getStr("snmp_location");
|
||||||
|
string contact =fw->getOptionsObject()->getStr("snmp_contact");
|
||||||
|
str << endl;
|
||||||
|
if (!location.empty()) str << "snmp-server location " << location << endl;
|
||||||
|
if (!contact.empty()) str << "snmp-server contact " << contact << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enable_traps) {
|
||||||
|
str << endl;
|
||||||
|
str << "snmp-server enable traps" << endl;
|
||||||
|
} else {
|
||||||
|
str << endl;
|
||||||
|
str << "no snmp-server enable traps" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
string snmp_server_1= fw->getOptionsObject()->getStr("pix_snmp_server1");
|
||||||
|
string snmp_server_2= fw->getOptionsObject()->getStr("pix_snmp_server2");
|
||||||
|
int snmp_poll_traps_1= fw->getOptionsObject()->getInt("pix_snmp_poll_traps_1");
|
||||||
|
int snmp_poll_traps_2= fw->getOptionsObject()->getInt("pix_snmp_poll_traps_2");
|
||||||
|
|
||||||
|
if (!snmp_server_1.empty())
|
||||||
|
str << _printSNMPServer(snmp_server_1,snmp_poll_traps_1);
|
||||||
|
|
||||||
|
if (!snmp_server_2.empty())
|
||||||
|
str << _printSNMPServer(snmp_server_2,snmp_poll_traps_2);
|
||||||
|
}
|
||||||
|
return str.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
string OSConfigurator_pix_os::_printNTPServer(const std::string &srv,bool pref)
|
||||||
|
{
|
||||||
|
Helper helper(this);
|
||||||
|
|
||||||
|
ostringstream str;
|
||||||
|
|
||||||
|
string iface_id=helper.findInterfaceByNetzone( IPAddress(srv) );
|
||||||
|
if (iface_id.empty()) abort("NTP server "+srv+" does not belong to any known network zone");
|
||||||
|
Interface *ntp_iface = getCachedFwInterface(iface_id);
|
||||||
|
str << "ntp server " << srv << " source " << ntp_iface->getLabel();
|
||||||
|
if (pref) str << " prefer";
|
||||||
|
str << endl;
|
||||||
|
|
||||||
|
return str.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
string OSConfigurator_pix_os::_printNTP()
|
||||||
|
{
|
||||||
|
ostringstream res;
|
||||||
|
string version = fw->getStr("version");
|
||||||
|
string platform = fw->getStr("platform");
|
||||||
|
string clearNTPcmd = Resources::platform_res[platform]->getResourceStr(
|
||||||
|
string("/FWBuilderResources/Target/options/version_")+
|
||||||
|
version+"/pix_commands/clear_ntp");
|
||||||
|
|
||||||
|
|
||||||
|
if ( !fw->getOptionsObject()->getBool("pix_acl_no_clear") )
|
||||||
|
res << clearNTPcmd << endl;
|
||||||
|
|
||||||
|
string ntp_server_1=fw->getOptionsObject()->getStr("pix_ntp1");
|
||||||
|
bool ntp1_pref=fw->getOptionsObject()->getBool("pix_ntp1_pref");
|
||||||
|
string ntp_server_2=fw->getOptionsObject()->getStr("pix_ntp2");
|
||||||
|
bool ntp2_pref=fw->getOptionsObject()->getBool("pix_ntp2_pref");
|
||||||
|
string ntp_server_3=fw->getOptionsObject()->getStr("pix_ntp3");
|
||||||
|
bool ntp3_pref=fw->getOptionsObject()->getBool("pix_ntp3_pref");
|
||||||
|
|
||||||
|
if (!ntp_server_1.empty())
|
||||||
|
res << _printNTPServer(ntp_server_1,ntp1_pref);
|
||||||
|
|
||||||
|
if (!ntp_server_2.empty())
|
||||||
|
res << _printNTPServer(ntp_server_2,ntp2_pref);
|
||||||
|
|
||||||
|
if (!ntp_server_3.empty())
|
||||||
|
res << _printNTPServer(ntp_server_3,ntp3_pref);
|
||||||
|
|
||||||
|
return res.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
string OSConfigurator_pix_os::_printSysopt()
|
||||||
|
{
|
||||||
|
ostringstream res;
|
||||||
|
string platform = fw->getStr("platform");
|
||||||
|
string version = fw->getStr("version");
|
||||||
|
|
||||||
|
FWOptions *options=fw->getOptionsObject();
|
||||||
|
assert(options!=NULL);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool tcpmss= fw->getOptionsObject()->getBool("pix_tcpmss");
|
||||||
|
int tcpmss_val=fw->getOptionsObject()->getInt("pix_tcpmss_value");
|
||||||
|
|
||||||
|
res << endl;
|
||||||
|
|
||||||
|
|
||||||
|
if (fw->getOptionsObject()->getBool("pix_resetinbound"))
|
||||||
|
res << "service resetinbound" << endl;
|
||||||
|
else
|
||||||
|
res << "no service resetinbound" << endl;
|
||||||
|
|
||||||
|
if (fw->getOptionsObject()->getBool("pix_resetoutside"))
|
||||||
|
res << "service resetoutside" << endl;
|
||||||
|
else
|
||||||
|
res << "no service resetoutside" << endl;
|
||||||
|
|
||||||
|
if (tcpmss)
|
||||||
|
res << "sysopt connection tcpmss " << tcpmss_val << endl;
|
||||||
|
|
||||||
|
if (fw->getStr("platform")=="pix")
|
||||||
|
{
|
||||||
|
if (fw->getOptionsObject()->getBool("pix_connection_timewait"))
|
||||||
|
res << "sysopt connection timewait" << endl;
|
||||||
|
else
|
||||||
|
res << "no sysopt connection timewait" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Resources::platform_res[platform]->getResourceBool(
|
||||||
|
"/FWBuilderResources/Target/options/version_"+version+
|
||||||
|
"/pix_security_fragguard_supported") )
|
||||||
|
{
|
||||||
|
if ( fw->getOptionsObject()->getBool("pix_fragguard") )
|
||||||
|
res << "sysopt security fragguard" << endl;
|
||||||
|
else
|
||||||
|
res << "no sysopt security fragguard" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( fw->getOptionsObject()->getBool("pix_nodnsalias_inbound") )
|
||||||
|
res << "sysopt nodnsalias inbound" << endl;
|
||||||
|
else
|
||||||
|
res << "no sysopt nodnsalias inbound" << endl;
|
||||||
|
|
||||||
|
if ( fw->getOptionsObject()->getBool("pix_nodnsalias_outbound") )
|
||||||
|
res << "sysopt nodnsalias outbound" << endl;
|
||||||
|
else
|
||||||
|
res << "no sysopt nodnsalias outbound" << endl;
|
||||||
|
|
||||||
|
if (Resources::platform_res[platform]->getResourceBool(
|
||||||
|
"/FWBuilderResources/Target/options/version_"+version+
|
||||||
|
"/pix_route_dnat_supported") )
|
||||||
|
{
|
||||||
|
if ( fw->getOptionsObject()->getBool("pix_route_dnat") )
|
||||||
|
res << "sysopt route dnat" << endl;
|
||||||
|
else
|
||||||
|
res << "no sysopt route dnat" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Resources::platform_res[platform]->getResourceBool(
|
||||||
|
"/FWBuilderResources/Target/options/version_"+version+
|
||||||
|
"/pix_floodguard_supported") )
|
||||||
|
{
|
||||||
|
if ( fw->getOptionsObject()->getBool("pix_floodguard") )
|
||||||
|
res << "floodguard enable" << endl;
|
||||||
|
else
|
||||||
|
res << "floodguard disable" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
res << endl;
|
||||||
|
|
||||||
|
return res.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
string OSConfigurator_pix_os::_printServiceTimeout(const std::string &pix_service)
|
||||||
|
{
|
||||||
|
ostringstream res;
|
||||||
|
string hh,mm,ss;
|
||||||
|
string version = fw->getStr("version");
|
||||||
|
string platform = fw->getStr("platform");
|
||||||
|
bool use_sunrpc = Resources::platform_res[platform]->getResourceBool(
|
||||||
|
"/FWBuilderResources/Target/options/version_"+version+
|
||||||
|
"/pix_timeout_rpc_is_sunrpc");
|
||||||
|
|
||||||
|
hh=fw->getOptionsObject()->getStr(pix_service+"_hh");
|
||||||
|
mm=fw->getOptionsObject()->getStr(pix_service+"_mm");
|
||||||
|
ss=fw->getOptionsObject()->getStr(pix_service+"_ss");
|
||||||
|
|
||||||
|
if (hh!="" && mm!="" && ss!="")
|
||||||
|
{
|
||||||
|
string service_name = pix_service;
|
||||||
|
if (pix_service=="rpc" && use_sunrpc)
|
||||||
|
service_name = "sunrpc";
|
||||||
|
|
||||||
|
res << "timeout " << service_name
|
||||||
|
<< " " << hh << ":" << mm << ":" << ss << " ";
|
||||||
|
|
||||||
|
if (pix_service=="uauth")
|
||||||
|
{
|
||||||
|
bool abs=fw->getOptionsObject()->getBool("uauth_abs");
|
||||||
|
bool inact=fw->getOptionsObject()->getBool("uauth_inact");
|
||||||
|
if (abs) res << "absolute";
|
||||||
|
if (inact) res << "inactivity";
|
||||||
|
}
|
||||||
|
res << endl;
|
||||||
|
}
|
||||||
|
return res.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
string OSConfigurator_pix_os::_printTimeouts()
|
||||||
|
{
|
||||||
|
ostringstream res;
|
||||||
|
|
||||||
|
res << _printServiceTimeout("xlate");
|
||||||
|
res << _printServiceTimeout("conn");
|
||||||
|
res << _printServiceTimeout("udp");
|
||||||
|
res << _printServiceTimeout("rpc");
|
||||||
|
res << _printServiceTimeout("h323");
|
||||||
|
res << _printServiceTimeout("sip");
|
||||||
|
res << _printServiceTimeout("sip_media");
|
||||||
|
res << _printServiceTimeout("half-closed");
|
||||||
|
res << _printServiceTimeout("uauth");
|
||||||
|
res << endl;
|
||||||
|
|
||||||
|
int to;
|
||||||
|
to=fw->getOptionsObject()->getInt("pix_telnet_timeout");
|
||||||
|
if (to>60) abort("Telnet timeout should not exceed 60 minutes");
|
||||||
|
if (to!=0) res << "telnet timeout " << to << endl;
|
||||||
|
|
||||||
|
to=fw->getOptionsObject()->getInt("pix_ssh_timeout");
|
||||||
|
if (to>60) abort("SSH timeout should not exceed 60 minutes");
|
||||||
|
if (to!=0) res << "ssh timeout " << to << endl;
|
||||||
|
|
||||||
|
return res.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OSConfigurator_pix_os::addVirtualAddressForNAT(const Address *addr)
|
||||||
|
{
|
||||||
|
if (addr==NULL) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSConfigurator_pix_os::addVirtualAddressForNAT(const Network *nw)
|
||||||
|
{
|
||||||
|
if (nw==NULL) ;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2002 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: OSConfigurator_pix_os.h,v 1.1 2008/03/06 06:49:00 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
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _OSNETWORKCONFIGURATOR_PIX_OS_HH
|
||||||
|
#define _OSNETWORKCONFIGURATOR_PIX_OS_HH
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "fwcompiler/OSConfigurator.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace fwcompiler {
|
||||||
|
|
||||||
|
class OSConfigurator_pix_os : public OSConfigurator {
|
||||||
|
|
||||||
|
std::string _printNameif();
|
||||||
|
std::string _printIPAddress();
|
||||||
|
|
||||||
|
std::string _printLogging();
|
||||||
|
std::string _printSNMPServer(const std::string &srv,int poll_trap);
|
||||||
|
std::string _printSNMP();
|
||||||
|
std::string _printSysopt();
|
||||||
|
std::string _printNTPServer(const std::string &srv,bool pref);
|
||||||
|
std::string _printNTP();
|
||||||
|
std::string _printServiceTimeout(const std::string &pix_service);
|
||||||
|
std::string _printTimeouts();
|
||||||
|
std::string _printFixupCommand(const std::string &fixup_name,
|
||||||
|
const std::string &sw,
|
||||||
|
int arg1,
|
||||||
|
int arg2,
|
||||||
|
bool ov);
|
||||||
|
std::string _printFixups();
|
||||||
|
std::string _printMPF();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~OSConfigurator_pix_os() {};
|
||||||
|
OSConfigurator_pix_os(libfwbuilder::FWObjectDatabase *_db,
|
||||||
|
const std::string &fwname) :
|
||||||
|
OSConfigurator(_db,fwname) {}
|
||||||
|
|
||||||
|
virtual int prolog();
|
||||||
|
|
||||||
|
virtual std::string myPlatformName();
|
||||||
|
virtual void processFirewallOptions();
|
||||||
|
virtual void addVirtualAddressForNAT(const libfwbuilder::Address *addr);
|
||||||
|
virtual void addVirtualAddressForNAT(const libfwbuilder::Network *nw);
|
||||||
|
|
||||||
|
std::string getProtocolInspectionCommands();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,447 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2002 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: OSConfigurator_pix_os_fixups.cpp,v 1.1 2008/03/06 06:49:00 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 "OSConfigurator_pix_os.h"
|
||||||
|
#include "Helper.h"
|
||||||
|
#include "fwbuilder/Resources.h"
|
||||||
|
|
||||||
|
#include "fwbuilder/Firewall.h"
|
||||||
|
#include "fwbuilder/FWOptions.h"
|
||||||
|
#include "fwbuilder/Interface.h"
|
||||||
|
#include "fwbuilder/Management.h"
|
||||||
|
#include "fwbuilder/Resources.h"
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace libfwbuilder;
|
||||||
|
using namespace fwcompiler;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
/* ********************************************************************
|
||||||
|
*
|
||||||
|
* Generating old school fixup commands for PIX 6.X
|
||||||
|
* and FWSM 2.3
|
||||||
|
*
|
||||||
|
* ********************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy this method into class PIXAdvancedFWDialog in fwbuilder/src/pix
|
||||||
|
*/
|
||||||
|
string OSConfigurator_pix_os::_printFixupCommand(const string &fixup_name,
|
||||||
|
const string &sw,
|
||||||
|
int arg1,
|
||||||
|
int arg2,
|
||||||
|
bool ov)
|
||||||
|
{
|
||||||
|
ostringstream res;
|
||||||
|
|
||||||
|
if (sw=="0")
|
||||||
|
{
|
||||||
|
if (fixup_name=="dns")
|
||||||
|
{
|
||||||
|
if (arg1)
|
||||||
|
{
|
||||||
|
res << "fixup protocol " << fixup_name;
|
||||||
|
res << " maximum-length " << arg1;
|
||||||
|
res << endl;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (fixup_name=="ftp")
|
||||||
|
{
|
||||||
|
if (arg1)
|
||||||
|
{
|
||||||
|
res << "fixup protocol " << fixup_name << " ";
|
||||||
|
if (ov) res << "strict ";
|
||||||
|
res << arg1;
|
||||||
|
res << endl;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (fixup_name=="mgcp")
|
||||||
|
{
|
||||||
|
if (arg1)
|
||||||
|
{
|
||||||
|
res << "fixup protocol " << fixup_name << " ";
|
||||||
|
res << arg1;
|
||||||
|
res << endl;
|
||||||
|
}
|
||||||
|
if (arg2)
|
||||||
|
{
|
||||||
|
res << "fixup protocol " << fixup_name << " ";
|
||||||
|
res << arg2;
|
||||||
|
res << endl;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
res << "fixup protocol " << fixup_name << " ";
|
||||||
|
if (arg1) res << arg1;
|
||||||
|
if (arg2 && arg1!=arg2) res << "-" << arg2;
|
||||||
|
res << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sw=="1")
|
||||||
|
{
|
||||||
|
res << "no fixup protocol " << fixup_name;
|
||||||
|
res << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
string OSConfigurator_pix_os::_printFixups()
|
||||||
|
{
|
||||||
|
ostringstream res;
|
||||||
|
string platform=fw->getStr("platform");
|
||||||
|
string version=fw->getStr("version");
|
||||||
|
|
||||||
|
FWOptions *options=fw->getOptionsObject();
|
||||||
|
assert(options!=NULL);
|
||||||
|
|
||||||
|
|
||||||
|
string lst=Resources::platform_res[platform]->getResourceStr(
|
||||||
|
"/FWBuilderResources/Target/options/version_"+version+"/fixups/list");
|
||||||
|
|
||||||
|
string::size_type i,j, k;
|
||||||
|
i=0;
|
||||||
|
while ( i<lst.size() )
|
||||||
|
{
|
||||||
|
j=lst.find(",",i);
|
||||||
|
string fixup_xml_element=lst.substr(i,j-i);
|
||||||
|
|
||||||
|
i=j+1;
|
||||||
|
|
||||||
|
string f=options->getStr(fixup_xml_element);
|
||||||
|
|
||||||
|
if (!f.empty())
|
||||||
|
{
|
||||||
|
string fixup_name=fixup_xml_element.substr(0, fixup_xml_element.find("_fixup") );
|
||||||
|
|
||||||
|
while ( (k=fixup_name.find("_"))!=string::npos )
|
||||||
|
fixup_name.replace(k,1,1,' ');
|
||||||
|
|
||||||
|
string sw;
|
||||||
|
int arg1,arg2;
|
||||||
|
string on;
|
||||||
|
bool ov;
|
||||||
|
istringstream str(f);
|
||||||
|
|
||||||
|
str >> sw >> arg1 >> arg2 >> on >> ov;
|
||||||
|
|
||||||
|
res << _printFixupCommand(fixup_name, sw, arg1, arg2, ov );
|
||||||
|
}
|
||||||
|
if (j==string::npos) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ********************************************************************
|
||||||
|
*
|
||||||
|
* Generating class-map, class and match commands instead of fixups
|
||||||
|
* for PIX 7.0
|
||||||
|
*
|
||||||
|
* ********************************************************************/
|
||||||
|
|
||||||
|
class InspectionProtocol;
|
||||||
|
std::map<std::string,InspectionProtocol*> protocols;
|
||||||
|
enum { FIXUP_ENABLE=0, FIXUP_DISABLE=1, FIXUP_SKIP=2 } fixupStatus;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* par1 and par2 are parameters for the inspection protocol. These are
|
||||||
|
* port numbers most of the time, but for some protocols the meaning
|
||||||
|
* may be different. For example for dns it is "maximum-length".
|
||||||
|
*/
|
||||||
|
class InspectionProtocol {
|
||||||
|
public:
|
||||||
|
|
||||||
|
string name;
|
||||||
|
string printable_name;
|
||||||
|
string ip_proto;
|
||||||
|
int par1,par2;
|
||||||
|
|
||||||
|
InspectionProtocol(const string &fn,
|
||||||
|
const string &prn,
|
||||||
|
const string &pn,
|
||||||
|
int p1,
|
||||||
|
int p2)
|
||||||
|
{
|
||||||
|
name=fn; printable_name=prn; ip_proto=pn; par1=p1; par2=p2;
|
||||||
|
if (protocols.count(fn)==0) protocols[fn]=this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default ports are defined here jsut like they are filled in the
|
||||||
|
* options by the GUI. If the GUI allows for port range, we specify
|
||||||
|
* port range here, and vice versa. Some of the cases seem to differ
|
||||||
|
* from what Cisco doc specify in the table of the default ports here
|
||||||
|
* http://www.cisco.com/en/US/products/sw/secursw/ps2120/products_upgrade_guides09186a0080369ee2.html
|
||||||
|
* I suppose this is ok since we always can use port range map with
|
||||||
|
* "match" command even if they did not intend it to be like that by
|
||||||
|
* default. However if the GUI returned port numbers that match those
|
||||||
|
* defined in protocolDefinitions, we do not generate 'match' commands
|
||||||
|
* at all and put everything in the "inspection_default" class-map
|
||||||
|
*
|
||||||
|
* Here is how this works: constructor of the class InspectionProtocols
|
||||||
|
* adds object to map 'protocols'. Every initialization of an object
|
||||||
|
* of this class in array protocolDefinitions calls constructor and
|
||||||
|
* therefore creates an entry in the map 'protocols'. It is done this
|
||||||
|
* way because we can statically initialize an array but cant initialize
|
||||||
|
* std::map (at least I do not know how)
|
||||||
|
*
|
||||||
|
* Note: in PIX 7.0 inspector that corresponds to fixup 'smtp' is
|
||||||
|
* called 'esmtp'
|
||||||
|
*/
|
||||||
|
InspectionProtocol protocolDefinitions[] =
|
||||||
|
{
|
||||||
|
InspectionProtocol("ctiqbe", "ctiqbe", "tcp", 2748, 0 ),
|
||||||
|
InspectionProtocol("dns", "dns", "udp", 53, 0 ),
|
||||||
|
InspectionProtocol("ftp", "ftp", "tcp", 21, 0 ),
|
||||||
|
InspectionProtocol("gtp", "gtp", "udp", 2123, 3386 ),
|
||||||
|
InspectionProtocol("h323_h225", "h323 h225", "tcp", 1720, 1720 ),
|
||||||
|
InspectionProtocol("h323_ras", "h323 ras", "udp", 1718, 1719 ),
|
||||||
|
InspectionProtocol("http", "http", "tcp", 80, 80 ),
|
||||||
|
InspectionProtocol("icmp_error","icmp", "icmp", 0, 0 ),
|
||||||
|
InspectionProtocol("ils", "ils", "tcp", 389, 389 ),
|
||||||
|
InspectionProtocol("mgcp", "mgcp", "udp", 2427, 2727 ),
|
||||||
|
InspectionProtocol("netbios", "netbios", "udp", 137, 138 ),
|
||||||
|
InspectionProtocol("rpc", "rpc", "udp", 111, 0 ),
|
||||||
|
InspectionProtocol("rsh", "rsh", "tcp", 514, 0 ),
|
||||||
|
InspectionProtocol("rtsp", "rtsp", "tcp", 554, 0 ),
|
||||||
|
InspectionProtocol("sip", "sip", "tcp", 5060, 5060 ),
|
||||||
|
InspectionProtocol("sip_udp", "sip", "udp", 5060, 0 ),
|
||||||
|
InspectionProtocol("skinny", "skinny", "tcp", 2000, 2000 ),
|
||||||
|
InspectionProtocol("smtp", "esmtp", "tcp", 25, 25 ),
|
||||||
|
InspectionProtocol("sqlnet", "sqlnet", "tcp", 1521, 1521 ),
|
||||||
|
InspectionProtocol("tftp", "tftp", "udp", 69, 0 ),
|
||||||
|
InspectionProtocol("xdmcp", "xdmcp", "udp", 177, 0 ),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* status:
|
||||||
|
* 0: enable
|
||||||
|
* 1: disable
|
||||||
|
* 2: skip
|
||||||
|
*/
|
||||||
|
class InspectionClassMap {
|
||||||
|
public:
|
||||||
|
|
||||||
|
string class_map_name;
|
||||||
|
string fixup_name;
|
||||||
|
string inspect_name;
|
||||||
|
int status;
|
||||||
|
int port1,port2;
|
||||||
|
string arg_name;
|
||||||
|
int arg_val;
|
||||||
|
|
||||||
|
InspectionClassMap(const string &fn,int s,int p1,int p2,const string &a,int v)
|
||||||
|
{
|
||||||
|
status=s; port1=p1; port2=p2; arg_name=a; arg_val=v;
|
||||||
|
string ss = fn;
|
||||||
|
string::size_type k;
|
||||||
|
while ( (k=ss.find(" "))!=string::npos )
|
||||||
|
ss.replace(k,1,1,'_');
|
||||||
|
inspect_name = ss;
|
||||||
|
fixup_name = fn;
|
||||||
|
class_map_name = string("custom_")+ss+string("_inspection");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isDefault();
|
||||||
|
string getIPProtocol();
|
||||||
|
string getPrintableName();
|
||||||
|
string getMatchCommand();
|
||||||
|
};
|
||||||
|
|
||||||
|
std::list<InspectionClassMap> defaultClassMaps;
|
||||||
|
std::list<InspectionClassMap> customClassMaps;
|
||||||
|
std::map<std::string,int> DefaultInspectionInspectStatements;
|
||||||
|
std::map<std::string,int> CustomInspectionInspectStatements;
|
||||||
|
|
||||||
|
bool InspectionClassMap::isDefault()
|
||||||
|
{
|
||||||
|
InspectionProtocol *ip = protocols[fixup_name];
|
||||||
|
if (ip!=NULL) return (ip->par1==port1 && ip->par2==port2);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string InspectionClassMap::getIPProtocol()
|
||||||
|
{
|
||||||
|
InspectionProtocol *ip = protocols[fixup_name];
|
||||||
|
if (ip!=NULL) return ip->ip_proto;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
string InspectionClassMap::getPrintableName()
|
||||||
|
{
|
||||||
|
InspectionProtocol *ip = protocols[fixup_name];
|
||||||
|
if (ip!=NULL) return ip->printable_name;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
string InspectionClassMap::getMatchCommand()
|
||||||
|
{
|
||||||
|
ostringstream res;
|
||||||
|
res << "match port " << getIPProtocol() << " ";
|
||||||
|
if (port1!=0 && port2==0)
|
||||||
|
res << "eq " << port1;
|
||||||
|
if (port1!=0 && port1==port2)
|
||||||
|
res << "eq " << port1;
|
||||||
|
if (port1!=0 && port2!=0 && port1!=port2)
|
||||||
|
res << "range " << port1 << " " << port2;
|
||||||
|
res << endl;
|
||||||
|
return res.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
string OSConfigurator_pix_os::_printMPF()
|
||||||
|
{
|
||||||
|
ostringstream res;
|
||||||
|
string platform=fw->getStr("platform");
|
||||||
|
string version=fw->getStr("version");
|
||||||
|
|
||||||
|
FWOptions *options=fw->getOptionsObject();
|
||||||
|
assert(options!=NULL);
|
||||||
|
|
||||||
|
string lst=Resources::platform_res[platform]->getResourceStr(
|
||||||
|
"/FWBuilderResources/Target/options/version_"+version+"/fixups/list");
|
||||||
|
|
||||||
|
defaultClassMaps.clear();
|
||||||
|
customClassMaps.clear();
|
||||||
|
DefaultInspectionInspectStatements.clear();
|
||||||
|
CustomInspectionInspectStatements.clear();
|
||||||
|
|
||||||
|
string::size_type i,j;
|
||||||
|
i=0;
|
||||||
|
while ( i<lst.size() )
|
||||||
|
{
|
||||||
|
j=lst.find(",",i);
|
||||||
|
string fixup_xml_element=lst.substr(i,j-i);
|
||||||
|
|
||||||
|
i=j+1;
|
||||||
|
|
||||||
|
string f=options->getStr(fixup_xml_element);
|
||||||
|
|
||||||
|
if (!f.empty())
|
||||||
|
{
|
||||||
|
string fixup_name=fixup_xml_element.substr(0, fixup_xml_element.find("_fixup") );
|
||||||
|
|
||||||
|
int status;
|
||||||
|
int p1,p2;
|
||||||
|
string an;
|
||||||
|
int av;
|
||||||
|
istringstream str(f);
|
||||||
|
|
||||||
|
str >> status >> p1 >> p2 >> an >> av;
|
||||||
|
|
||||||
|
/* We should really fix this in the GUI and pass max length parameter
|
||||||
|
* as an/av rather than as port p1
|
||||||
|
*/
|
||||||
|
if (fixup_name=="dns" && p1!=0) { an="maximum-length"; av=p1; p1=53; }
|
||||||
|
|
||||||
|
InspectionClassMap cm(fixup_name,status,p1,p2,an,av);
|
||||||
|
if (cm.isDefault()) defaultClassMaps.push_back(cm);
|
||||||
|
else customClassMaps.push_back(cm);
|
||||||
|
}
|
||||||
|
if (j==string::npos) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
res << "class-map inspection_default" << endl;
|
||||||
|
res << " match default-inspection-traffic" << endl;
|
||||||
|
res << endl;
|
||||||
|
|
||||||
|
std::list<InspectionClassMap>::iterator i1;
|
||||||
|
|
||||||
|
if (customClassMaps.size()>0)
|
||||||
|
{
|
||||||
|
for (i1=customClassMaps.begin(); i1!=customClassMaps.end(); i1++)
|
||||||
|
{
|
||||||
|
res << "class-map " << i1->class_map_name << endl;
|
||||||
|
res << " " << i1->getMatchCommand() << endl;
|
||||||
|
}
|
||||||
|
res << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
res << "policy-map global_policy" << endl;
|
||||||
|
if (defaultClassMaps.size()>0)
|
||||||
|
{
|
||||||
|
res << " class inspection_default" << endl;
|
||||||
|
for (i1=defaultClassMaps.begin(); i1!=defaultClassMaps.end(); i1++)
|
||||||
|
{
|
||||||
|
string pn = i1->getPrintableName();
|
||||||
|
if (i1->status!=FIXUP_SKIP &&
|
||||||
|
DefaultInspectionInspectStatements[pn]!=1)
|
||||||
|
{
|
||||||
|
res << " ";
|
||||||
|
if (i1->status==FIXUP_DISABLE) res << "no ";
|
||||||
|
res << "inspect " << pn << endl;
|
||||||
|
DefaultInspectionInspectStatements[pn]=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (customClassMaps.size()>0)
|
||||||
|
{
|
||||||
|
for (i1=customClassMaps.begin(); i1!=customClassMaps.end(); i1++)
|
||||||
|
{
|
||||||
|
string pn = i1->getPrintableName();
|
||||||
|
if (i1->status!=FIXUP_SKIP &&
|
||||||
|
CustomInspectionInspectStatements[pn]!=1)
|
||||||
|
{
|
||||||
|
res << " class " << i1->class_map_name << endl;
|
||||||
|
res << " ";
|
||||||
|
if (i1->status==FIXUP_DISABLE) res << "no ";
|
||||||
|
res << "inspect " << i1->getPrintableName() << endl;
|
||||||
|
CustomInspectionInspectStatements[pn]=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res << endl;
|
||||||
|
|
||||||
|
res << "service-policy global_policy global" << endl;
|
||||||
|
|
||||||
|
return res.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string OSConfigurator_pix_os::getProtocolInspectionCommands()
|
||||||
|
{
|
||||||
|
string platform=fw->getStr("platform");
|
||||||
|
string version=fw->getStr("version");
|
||||||
|
|
||||||
|
if (Resources::platform_res[platform]->getResourceBool(
|
||||||
|
"/FWBuilderResources/Target/options/version_"+version+"/fixups/use_mpf"))
|
||||||
|
return _printMPF();
|
||||||
|
|
||||||
|
return _printFixups();
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2002 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: PIXObjectGroup.cpp,v 1.1 2008/03/06 06:49:00 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 "config.h"
|
||||||
|
|
||||||
|
#include "PIXObjectGroup.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
map<string,int> PIXGroup::nc;
|
||||||
|
|
||||||
|
const char *PIXGroup::TYPENAME={"PIXGroup"};
|
||||||
|
|
||||||
|
string PIXGroup::registerGroupName(const std::string &prefix)
|
||||||
|
{
|
||||||
|
ostringstream str;
|
||||||
|
str << prefix;
|
||||||
|
|
||||||
|
switch (getPIXGroupType())
|
||||||
|
{
|
||||||
|
case UNKNOWN: str << ".unknown"; break;
|
||||||
|
case NETWORK: str << ".net"; break;
|
||||||
|
case PROTO: str << ".proto"; break;
|
||||||
|
case ICMP_TYPE: str << ".icmp"; break;
|
||||||
|
case TCP_SERVICE: str << ".tcp"; break;
|
||||||
|
case UDP_SERVICE: str << ".udp"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int n=nc[str.str()];
|
||||||
|
nc[str.str()]=n+1;
|
||||||
|
str << "." << n;
|
||||||
|
return str.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PIXGroup::setName(const std::string &prefix)
|
||||||
|
{
|
||||||
|
FWObject::setName( registerGroupName(prefix) );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PIXGroup::isServiceGroup()
|
||||||
|
{
|
||||||
|
switch (getPIXGroupType())
|
||||||
|
{
|
||||||
|
case PROTO: return true;
|
||||||
|
case ICMP_TYPE: return true;
|
||||||
|
case TCP_SERVICE: return true;
|
||||||
|
case UDP_SERVICE: return true;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PIXGroup::isObjectGroup()
|
||||||
|
{
|
||||||
|
switch (getPIXGroupType())
|
||||||
|
{
|
||||||
|
case UNKNOWN: return true;
|
||||||
|
case NETWORK: return true;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string PIXGroup::getSrvTypeName()
|
||||||
|
{
|
||||||
|
switch (getPIXGroupType())
|
||||||
|
{
|
||||||
|
case ICMP_TYPE: return "icmp";
|
||||||
|
case TCP_SERVICE: return "tcp";
|
||||||
|
case UDP_SERVICE: return "udp";
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
void PIXServiceGroup::setName(const std::string &prefix)
|
||||||
|
{
|
||||||
|
FWObject::setName( registerGroupName(prefix) );
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *PIXObjectGroup::TYPENAME={"PIXObjectGroup"};
|
||||||
|
|
||||||
|
PIXObjectGroup::PIXObjectGroup(pix_group_type _gt) :
|
||||||
|
ObjectGroup(), PIXGroup(_gt) {}
|
||||||
|
|
||||||
|
|
||||||
|
const char *PIXServiceGroup::TYPENAME={"PIXServiceGroup"};
|
||||||
|
|
||||||
|
PIXServiceGroup::PIXServiceGroup(pix_group_type _gt) :
|
||||||
|
ServiceGroup(), PIXGroup(_gt) {}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2002 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: PIXObjectGroup.h,v 1.1 2008/03/06 06:49:00 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
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __PIXOBJECTGROUP_HH
|
||||||
|
#define __PIXOBJECTGROUP_HH
|
||||||
|
|
||||||
|
#include "fwbuilder/FWObject.h"
|
||||||
|
#include "fwbuilder/ObjectGroup.h"
|
||||||
|
#include "fwbuilder/ServiceGroup.h"
|
||||||
|
|
||||||
|
typedef enum { UNKNOWN,
|
||||||
|
NETWORK,
|
||||||
|
PROTO,
|
||||||
|
ICMP_TYPE,
|
||||||
|
TCP_SERVICE,
|
||||||
|
UDP_SERVICE } pix_group_type;
|
||||||
|
|
||||||
|
class PIXGroup : public libfwbuilder::Group {
|
||||||
|
private:
|
||||||
|
pix_group_type gt;
|
||||||
|
static std::map<std::string,int> nc;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string registerGroupName(const std::string &prefix);
|
||||||
|
|
||||||
|
public:
|
||||||
|
PIXGroup(pix_group_type _gt=UNKNOWN) : libfwbuilder::Group() { gt=_gt; }
|
||||||
|
virtual ~PIXGroup() {};
|
||||||
|
DECLARE_FWOBJECT_SUBTYPE(PIXGroup);
|
||||||
|
|
||||||
|
virtual bool validateChild(FWObject *o) { return true; }
|
||||||
|
|
||||||
|
void setPIXGroupType(pix_group_type _gt) { gt=_gt; }
|
||||||
|
pix_group_type getPIXGroupType() { return gt; }
|
||||||
|
virtual void setName(const std::string &prefix);
|
||||||
|
|
||||||
|
bool isServiceGroup();
|
||||||
|
bool isObjectGroup();
|
||||||
|
std::string getSrvTypeName();
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
class PIXObjectGroup : public libfwbuilder::ObjectGroup
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
pix_group_type gt;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PIXObjectGroup(pix_group_type _gt=NETWORK) : ObjectGroup() { gt=_gt; }
|
||||||
|
virtual ~PIXObjectGroup() {};
|
||||||
|
DECLARE_FWOBJECT_SUBTYPE(PIXObjectGroup);
|
||||||
|
|
||||||
|
virtual bool validateChild(FWObject *o) { if (o==NULL) ; return true; }
|
||||||
|
virtual void setName(const std::string &prefix);
|
||||||
|
};
|
||||||
|
|
||||||
|
class PIXServiceGroup : public libfwbuilder::ServiceGroup
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
pix_group_type gt;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PIXServiceGroup(pix_group_type _gt=UNKNOWN) : ServiceGroup() { gt=_gt; }
|
||||||
|
virtual ~PIXServiceGroup() {};
|
||||||
|
DECLARE_FWOBJECT_SUBTYPE(PIXServiceGroup);
|
||||||
|
|
||||||
|
virtual bool validateChild(FWObject *o) { if (o==NULL) ; return true; }
|
||||||
|
virtual void setName(const std::string &prefix);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,845 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2002 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: PolicyCompiler_pix.cpp,v 1.1 2008/03/06 06:49:00 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 "config.h"
|
||||||
|
|
||||||
|
#include "Helper.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;
|
||||||
|
|
||||||
|
string PolicyCompiler_pix::myPlatformName() { return "pix"; }
|
||||||
|
|
||||||
|
PolicyCompiler_pix::PolicyCompiler_pix(FWObjectDatabase *_db,
|
||||||
|
const std::string &fwname,
|
||||||
|
OSConfigurator *_oscnf,
|
||||||
|
NATCompiler_pix *_natcmp) :
|
||||||
|
PolicyCompiler_cisco(_db,fwname,_oscnf)
|
||||||
|
{
|
||||||
|
natcmp=_natcmp;
|
||||||
|
resetinbound=false;
|
||||||
|
fragguard=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PolicyCompiler_pix::prolog()
|
||||||
|
{
|
||||||
|
string version = fw->getStr("version");
|
||||||
|
string platform = fw->getStr("platform");
|
||||||
|
string host_os = fw->getStr("host_OS");
|
||||||
|
|
||||||
|
if (platform!="pix" && platform!="fwsm")
|
||||||
|
abort("Unsupported platform " + platform );
|
||||||
|
|
||||||
|
object_groups=new Group();
|
||||||
|
dbcopy->add( object_groups );
|
||||||
|
|
||||||
|
output << "!################" << endl;
|
||||||
|
|
||||||
|
if (platform=="fwsm")
|
||||||
|
{
|
||||||
|
if (fw->getOptionsObject()->getBool("pix_use_manual_commit") )
|
||||||
|
output << "access-list mode manual" << endl;
|
||||||
|
else
|
||||||
|
output << "access-list mode auto" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( fw->getOptionsObject()->getBool("pix_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("pix_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");
|
||||||
|
}
|
||||||
|
|
||||||
|
string::size_type slash_idx = temp_acl_addr.find('/');
|
||||||
|
string addr = temp_acl_addr;
|
||||||
|
string netmask = "255.255.255.255";
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
Netmask nm(netmask);
|
||||||
|
nm.to32BitInt(); // to avoid warning abt unused var
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
int nm_length;
|
||||||
|
istringstream str(netmask);
|
||||||
|
str >> nm_length;
|
||||||
|
Netmask nm(nm_length);
|
||||||
|
netmask = nm.toString();
|
||||||
|
}
|
||||||
|
} catch(FWException &ex)
|
||||||
|
{
|
||||||
|
abort("Invalid netmask for management subnet: '"+netmask+"'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IPAddress a(addr);
|
||||||
|
a.to32BitInt();
|
||||||
|
} catch(FWException &ex)
|
||||||
|
{
|
||||||
|
abort("Invalid address for management subnet: '"+addr+"'");
|
||||||
|
}
|
||||||
|
|
||||||
|
string clearACLcmd = Resources::platform_res[platform]->getResourceStr(
|
||||||
|
string("/FWBuilderResources/Target/options/")+
|
||||||
|
"version_"+version+"/pix_commands/clear_acl");
|
||||||
|
|
||||||
|
output << endl;
|
||||||
|
|
||||||
|
output << clearACLcmd << " " << temp_acl << endl;
|
||||||
|
output << "access-list " << temp_acl
|
||||||
|
<< " permit ip "
|
||||||
|
<< addr << " " << netmask
|
||||||
|
<< " any "
|
||||||
|
<< endl;
|
||||||
|
output << "access-list " << temp_acl
|
||||||
|
<< " deny ip any any "
|
||||||
|
<< endl;
|
||||||
|
if (platform=="fwsm" &&
|
||||||
|
fw->getOptionsObject()->getBool("pix_use_manual_commit") )
|
||||||
|
output << "access-list commit" << endl;
|
||||||
|
|
||||||
|
output << endl;
|
||||||
|
|
||||||
|
output << "access-group " << temp_acl
|
||||||
|
<< " in interface outside" << endl;
|
||||||
|
output << "access-group " << temp_acl
|
||||||
|
<< " in interface inside" << endl;
|
||||||
|
|
||||||
|
output << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PolicyCompiler::prolog();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyCompiler_pix::checkVersionAndDynamicInterface::findDynamicInterface(
|
||||||
|
PolicyRule *rule, RuleElement *rel)
|
||||||
|
{
|
||||||
|
string vers=compiler->fw->getStr("version");
|
||||||
|
for (list<FWObject*>::iterator i1=rel->begin(); i1!=rel->end(); ++i1)
|
||||||
|
{
|
||||||
|
FWObject *o = *i1;
|
||||||
|
FWObject *obj = NULL;
|
||||||
|
if (FWReference::cast(o)!=NULL) obj=FWReference::cast(o)->getPointer();
|
||||||
|
Interface *iface=Interface::cast(obj);
|
||||||
|
if (iface!=NULL && iface->isDyn() && (vers=="6.1" || vers=="6.2"))
|
||||||
|
compiler->abort("Dynamic interface can be used in the policy rule only in v6.3 or later. Rule "+rule->getLabel());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyCompiler_pix::checkVersionAndDynamicInterface::processNext()
|
||||||
|
{
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
Service *s=compiler->getFirstSrv(rule);
|
||||||
|
|
||||||
|
/* if service is ssh, telnet or icmp then we can use dynamic interface
|
||||||
|
* even in earlier versions */
|
||||||
|
if (ICMPService::isA(s)) return true;
|
||||||
|
if (TCPService::isA(s))
|
||||||
|
{
|
||||||
|
if ( s->getInt("dst_range_start")==22 &&
|
||||||
|
s->getInt("dst_range_end")==22) return true;
|
||||||
|
if ( s->getInt("dst_range_start")==23 &&
|
||||||
|
s->getInt("dst_range_end")==23) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
findDynamicInterface(rule,rule->getSrc());
|
||||||
|
findDynamicInterface(rule,rule->getDst());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyCompiler_pix::SpecialServices::processNext()
|
||||||
|
{
|
||||||
|
PolicyCompiler_pix *pix_comp=dynamic_cast<PolicyCompiler_pix*>(compiler);
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
Service *s=compiler->getFirstSrv(rule);
|
||||||
|
|
||||||
|
if (IPService::cast(s)!=NULL) {
|
||||||
|
if (s->getBool("short_fragm") ||
|
||||||
|
s->getBool("fragm") ) {
|
||||||
|
|
||||||
|
pix_comp->fragguard=true;
|
||||||
|
return true; // do not copy the rule
|
||||||
|
}
|
||||||
|
if (s->getBool("rr") ||
|
||||||
|
s->getBool("ssrr") ||
|
||||||
|
s->getBool("ts") )
|
||||||
|
compiler->abort("PIX does not support checking for IP options in ACLs. Rule: "+rule->getLabel());
|
||||||
|
}
|
||||||
|
if (TCPService::cast(s)!=NULL) {
|
||||||
|
if (s->getBool("ack_flag") ||
|
||||||
|
s->getBool("fin_flag") ||
|
||||||
|
s->getBool("rst_flag") ||
|
||||||
|
s->getBool("syn_flag") )
|
||||||
|
compiler->abort("PIX does not support checking for TCP options in ACLs. Rule: "+rule->getLabel());
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if dst contains firewall, it must be a single object there.
|
||||||
|
*/
|
||||||
|
bool PolicyCompiler_pix::PrepareForICMPCmd::processNext()
|
||||||
|
{
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
|
||||||
|
Address *dst=compiler->getFirstDst(rule);
|
||||||
|
Service *srv=compiler->getFirstSrv(rule);
|
||||||
|
|
||||||
|
if (ICMPService::isA(srv) &&
|
||||||
|
compiler->complexMatch(dst,compiler->fw))
|
||||||
|
rule->setBool("icmp_cmd",true);
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PolicyCompiler_pix::SplitSRCForICMPCmd::processNext()
|
||||||
|
{
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
|
||||||
|
if (rule->getBool("icmp_cmd"))
|
||||||
|
{
|
||||||
|
|
||||||
|
RuleElementSrc *src=rule->getSrc();
|
||||||
|
if (src->size()==1)
|
||||||
|
{
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (FWObject::iterator i=src->begin(); i!=src->end(); ++i)
|
||||||
|
{
|
||||||
|
FWObject *o = *i;
|
||||||
|
FWObject *obj = NULL;
|
||||||
|
if (FWReference::cast(o)!=NULL) obj=FWReference::cast(o)->getPointer();
|
||||||
|
Address *a=Address::cast(obj);
|
||||||
|
assert(a!=NULL);
|
||||||
|
|
||||||
|
PolicyRule *new_rule= PolicyRule::cast(compiler->dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
compiler->temp_ruleset->add(new_rule);
|
||||||
|
new_rule->duplicate(rule);
|
||||||
|
RuleElementSrc *new_re=new_rule->getSrc();
|
||||||
|
new_re->clearChildren();
|
||||||
|
new_re->addRef(a);
|
||||||
|
|
||||||
|
tmp_queue.push_back(new_rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* About "service resetinbound" command:
|
||||||
|
*
|
||||||
|
* "The service command works with all inbound TCP connections to
|
||||||
|
* statics whose access lists or uauth (user authorization) do not
|
||||||
|
* allow inbound"
|
||||||
|
*/
|
||||||
|
bool PolicyCompiler_pix::RejectAction::processNext()
|
||||||
|
{
|
||||||
|
PolicyCompiler_pix *pix_comp=dynamic_cast<PolicyCompiler_pix*>(compiler);
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
|
||||||
|
if (rule->getAction()==PolicyRule::Reject)
|
||||||
|
pix_comp->resetinbound=true;
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyCompiler_pix::replaceNATtedObjects::processNext()
|
||||||
|
{
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
PolicyCompiler_pix *pix_comp=dynamic_cast<PolicyCompiler_pix*>(compiler);
|
||||||
|
Interface *rule_iface = compiler->getCachedFwInterface(rule->getInterfaceId());
|
||||||
|
// string rule_iface_id=rule->getInterfaceId();
|
||||||
|
|
||||||
|
// Address *src=compiler->getFirstSrc(rule);
|
||||||
|
// Service *srv=compiler->getFirstSrv(rule);
|
||||||
|
|
||||||
|
RuleElementSrc *srcrel=rule->getSrc();
|
||||||
|
RuleElementDst *dstrel=rule->getDst();
|
||||||
|
RuleElementSrv *srvrel=rule->getSrv();
|
||||||
|
|
||||||
|
list<PolicyRule*> t_rules;
|
||||||
|
list<PolicyRule*> transformed_rules;
|
||||||
|
|
||||||
|
for (list<FWObject*>::iterator i1=srcrel->begin(); i1!=srcrel->end(); ++i1)
|
||||||
|
{
|
||||||
|
for (list<FWObject*>::iterator i2=dstrel->begin(); i2!=dstrel->end(); ++i2)
|
||||||
|
{
|
||||||
|
for (list<FWObject*>::iterator i3=srvrel->begin(); i3!=srvrel->end(); ++i3)
|
||||||
|
{
|
||||||
|
FWObject *o1 = *i1;
|
||||||
|
FWObject *o2 = *i2;
|
||||||
|
FWObject *o3 = *i3;
|
||||||
|
FWObject *obj1 = NULL;
|
||||||
|
FWObject *obj2 = NULL;
|
||||||
|
FWObject *obj3 = NULL;
|
||||||
|
|
||||||
|
if (FWReference::cast(o1)!=NULL)
|
||||||
|
obj1=FWReference::cast(o1)->getPointer();
|
||||||
|
Address *src=Address::cast(obj1);
|
||||||
|
assert(src!=NULL);
|
||||||
|
|
||||||
|
if (FWReference::cast(o2)!=NULL)
|
||||||
|
obj2=FWReference::cast(o2)->getPointer();
|
||||||
|
Address *dst=Address::cast(obj2);
|
||||||
|
assert(dst!=NULL);
|
||||||
|
|
||||||
|
if (FWReference::cast(o3)!=NULL)
|
||||||
|
obj3=FWReference::cast(o3)->getPointer();
|
||||||
|
Service *srv=Service::cast(obj3);
|
||||||
|
assert(srv!=NULL);
|
||||||
|
|
||||||
|
list<triplet> tl = pix_comp->natcmp->findDNATForAddress(
|
||||||
|
src,dst,srv);
|
||||||
|
|
||||||
|
for( list<triplet>::iterator t=tl.begin(); t!=tl.end(); ++t)
|
||||||
|
{
|
||||||
|
FWObject *p = t->dst->getParent();
|
||||||
|
if (t->dst->getId()==rule_iface->getId() ||
|
||||||
|
p->getId()==rule_iface->getId())
|
||||||
|
{
|
||||||
|
PolicyRule *r = PolicyRule::cast(
|
||||||
|
compiler->dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
compiler->temp_ruleset->add(r);
|
||||||
|
r->duplicate(rule);
|
||||||
|
|
||||||
|
RuleElementSrc *nsrc=r->getSrc();
|
||||||
|
nsrc->clearChildren();
|
||||||
|
nsrc->addRef( src );
|
||||||
|
|
||||||
|
RuleElementDst *ndst=r->getDst();
|
||||||
|
ndst->clearChildren();
|
||||||
|
ndst->addRef( t->dst );
|
||||||
|
|
||||||
|
RuleElementSrv *nsrv=r->getSrv();
|
||||||
|
nsrv->clearChildren();
|
||||||
|
nsrv->addRef( t->srv );
|
||||||
|
|
||||||
|
t_rules.push_back(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* list t_rules has all the atomic rules that have a
|
||||||
|
* matching NAT rule, with dst and srv already converted. We just add them to
|
||||||
|
* the policy on top of the original rule.
|
||||||
|
*/
|
||||||
|
for (list<PolicyRule*>::iterator i1=t_rules.begin(); i1!=t_rules.end(); ++i1)
|
||||||
|
{
|
||||||
|
PolicyRule *r=PolicyRule::cast( *i1 );
|
||||||
|
tmp_queue.push_back(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* processor splitIfDstMatchesFw should have made a firewall a single
|
||||||
|
* object in dst
|
||||||
|
*/
|
||||||
|
bool PolicyCompiler_pix::splitIfTelnetSSHICMPtoFw::processNext()
|
||||||
|
{
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
// PolicyCompiler_pix *pix_comp=dynamic_cast<PolicyCompiler_pix*>(compiler);
|
||||||
|
|
||||||
|
Address *dst=compiler->getFirstDst(rule);
|
||||||
|
RuleElement *re=rule->getSrc();
|
||||||
|
if (re->size()!=1 && dst->getId()==compiler->getFwId())
|
||||||
|
{
|
||||||
|
for (FWObject::iterator i1=re->begin(); i1!=re->end(); ++i1)
|
||||||
|
{
|
||||||
|
FWObject *o = *i1;
|
||||||
|
FWObject *obj = o;
|
||||||
|
if (FWReference::cast(o)!=NULL) obj=FWReference::cast(o)->getPointer();
|
||||||
|
|
||||||
|
PolicyRule *r= PolicyRule::cast(compiler->dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
compiler->temp_ruleset->add(r);
|
||||||
|
r->duplicate(rule);
|
||||||
|
|
||||||
|
RuleElementSrc *nsrc=r->getSrc();
|
||||||
|
nsrc->clearChildren();
|
||||||
|
nsrc->addRef( obj );
|
||||||
|
tmp_queue.push_back(r);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this is probably not necessary. PIX prints all acl rules with
|
||||||
|
* object-groups twice: first time as entered, with object-group, and
|
||||||
|
* the second time it expands the group (for convenience ?). I thought
|
||||||
|
* it does not print original rule for icmp but it looks like it it
|
||||||
|
* does it for icmp just like for other protocols. PIX is ok, I made a
|
||||||
|
* mistake. I keep with rule processor just in case, but comment out
|
||||||
|
* the call to it.
|
||||||
|
*/
|
||||||
|
bool PolicyCompiler_pix::AvoidObjectGroup::processNext()
|
||||||
|
{
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
// PolicyCompiler_pix *pix_comp=dynamic_cast<PolicyCompiler_pix*>(compiler);
|
||||||
|
|
||||||
|
RuleElement *srv=RuleElement::cast(rule->getFirstByType(RuleElementSrv::TYPENAME));
|
||||||
|
if (srv->size()==1) // no need to create object-group since there is single object in the rule element
|
||||||
|
{
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
FWObject *o = srv->front();
|
||||||
|
if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
|
||||||
|
if (ICMPService::isA(o))
|
||||||
|
{
|
||||||
|
/* we have a rule with multiple icmp services in Srv. We do not want
|
||||||
|
* to use object-group for it because PIX 6.3(3) expands them anyway,
|
||||||
|
* which breaks incremental installer.
|
||||||
|
*/
|
||||||
|
for (FWObject::iterator i1=srv->begin(); i1!=srv->end(); ++i1)
|
||||||
|
{
|
||||||
|
PolicyRule *r = PolicyRule::cast(
|
||||||
|
compiler->dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
r->duplicate(rule);
|
||||||
|
compiler->temp_ruleset->add(r);
|
||||||
|
|
||||||
|
FWObject *s;
|
||||||
|
s=r->getSrv(); assert(s);
|
||||||
|
s->clearChildren();
|
||||||
|
s->add( *i1 );
|
||||||
|
|
||||||
|
tmp_queue.push_back(r);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PIXGroup* PolicyCompiler_pix::CreateObjectGroups::findObjectGroup(RuleElement *re)
|
||||||
|
{
|
||||||
|
PolicyCompiler_pix *pix_comp=dynamic_cast<PolicyCompiler_pix*>(compiler);
|
||||||
|
|
||||||
|
list<FWObject*> relement;
|
||||||
|
|
||||||
|
for (FWObject::iterator i1=re->begin(); i1!=re->end(); ++i1)
|
||||||
|
{
|
||||||
|
FWObject *o = *i1;
|
||||||
|
FWObject *obj = o;
|
||||||
|
if (FWReference::cast(o)!=NULL) obj=FWReference::cast(o)->getPointer();
|
||||||
|
|
||||||
|
relement.push_back(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (FWObject::iterator i=pix_comp->object_groups->begin();
|
||||||
|
i!=pix_comp->object_groups->end(); ++i)
|
||||||
|
{
|
||||||
|
PIXGroup *og=dynamic_cast<PIXGroup*>(*i);
|
||||||
|
assert(og!=NULL);
|
||||||
|
|
||||||
|
if (og->size()==0 || (og->size()!=re->size()) ) continue;
|
||||||
|
|
||||||
|
bool match=true;
|
||||||
|
for (FWObject::iterator i1=og->begin(); i1!=og->end(); ++i1)
|
||||||
|
{
|
||||||
|
FWObject *o = *i1;
|
||||||
|
FWObject *obj = o;
|
||||||
|
if (FWReference::cast(o)!=NULL) obj=FWReference::cast(o)->getPointer();
|
||||||
|
|
||||||
|
if ( find(relement.begin(), relement.end(), obj)==relement.end() )
|
||||||
|
{
|
||||||
|
match=false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (match) return og;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyCompiler_pix::CreateObjectGroups::processNext()
|
||||||
|
{
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
PolicyCompiler_pix *pix_comp=dynamic_cast<PolicyCompiler_pix*>(compiler);
|
||||||
|
Interface *rule_iface = compiler->getCachedFwInterface(rule->getInterfaceId());
|
||||||
|
assert(rule_iface);
|
||||||
|
|
||||||
|
RuleElement *re=RuleElement::cast(rule->getFirstByType(re_type));
|
||||||
|
if (re->size()==1) // no need to create object-group since there is single object in the rule element
|
||||||
|
{
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PIXGroup *obj_group=findObjectGroup(re);
|
||||||
|
if (obj_group==NULL)
|
||||||
|
{
|
||||||
|
obj_group= new PIXGroup();
|
||||||
|
|
||||||
|
FWObject *o=re->front();
|
||||||
|
FWObject *obj = o;
|
||||||
|
if (FWReference::cast(o)!=NULL) obj=FWReference::cast(o)->getPointer();
|
||||||
|
|
||||||
|
if (Address::cast(obj)!=NULL) obj_group->setPIXGroupType(NETWORK);
|
||||||
|
if (IPService::cast(obj)!=NULL) obj_group->setPIXGroupType(PROTO);
|
||||||
|
if (ICMPService::cast(obj)!=NULL) obj_group->setPIXGroupType(ICMP_TYPE);
|
||||||
|
if (TCPService::cast(obj)!=NULL) obj_group->setPIXGroupType(TCP_SERVICE);
|
||||||
|
if (UDPService::cast(obj)!=NULL) obj_group->setPIXGroupType(UDP_SERVICE);
|
||||||
|
|
||||||
|
obj_group->setName(
|
||||||
|
rule_iface->getLabel()+"."+rule->getUniqueId()+"."+name_suffix);
|
||||||
|
|
||||||
|
pix_comp->object_groups->add(obj_group);
|
||||||
|
pix_comp->cacheObj(obj_group);
|
||||||
|
|
||||||
|
for (FWObject::iterator i1=re->begin(); i1!=re->end(); ++i1)
|
||||||
|
{
|
||||||
|
FWObject *o = *i1;
|
||||||
|
FWObject *obj = o;
|
||||||
|
if (FWReference::cast(o)!=NULL) obj=FWReference::cast(o)->getPointer();
|
||||||
|
obj_group->addRef( obj );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
re->clearChildren(false); // do not want to destroy children objects
|
||||||
|
|
||||||
|
re->addRef(obj_group);
|
||||||
|
|
||||||
|
assert(re->size()==1);
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolicyCompiler_pix::compile()
|
||||||
|
{
|
||||||
|
cout << " Compiling policy for " << fw->getName() << " ..." << endl << flush;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string vers = fw->getStr("version");
|
||||||
|
string platform = fw->getStr("platform");
|
||||||
|
bool outbound_acl_supported = Resources::platform_res[platform]->getResourceBool(
|
||||||
|
string("/FWBuilderResources/Target/options/")+
|
||||||
|
"version_"+vers+
|
||||||
|
"/pix_outbound_acl_supported");
|
||||||
|
bool generate_out_acl = fw->getOptionsObject()->getBool("pix_generate_out_acl");
|
||||||
|
|
||||||
|
if (outbound_acl_supported && !generate_out_acl)
|
||||||
|
{
|
||||||
|
// behave like if outbound acls are not supported but are emulated
|
||||||
|
outbound_acl_supported = false;
|
||||||
|
fw->getOptionsObject()->setBool("pix_emulate_out_acl", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Compiler::compile();
|
||||||
|
|
||||||
|
addDefaultPolicyRule();
|
||||||
|
|
||||||
|
if ( fw->getOptionsObject()->getBool ("check_shading"))
|
||||||
|
{
|
||||||
|
add( new Begin ("Detecting rule shadowing" ));
|
||||||
|
add( new printTotalNumberOfRules ( ));
|
||||||
|
|
||||||
|
add( new ItfNegation( "process negation in Itf" ));
|
||||||
|
add( new InterfacePolicyRules("process interface policy rules and store interface ids"));
|
||||||
|
|
||||||
|
add( new recursiveGroupsInSrc( "check for recursive groups in SRC" ));
|
||||||
|
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 eliminateDuplicatesInSRC ("eliminate duplicates in SRC" ));
|
||||||
|
add( new eliminateDuplicatesInDST ("eliminate duplicates in DST" ));
|
||||||
|
add( new eliminateDuplicatesInSRV ("eliminate duplicates in SRV" ));
|
||||||
|
add( new ExpandMultipleAddressesInSRC("expand objects with multiple addresses in SRC" ));
|
||||||
|
add( new ExpandMultipleAddressesInDST("expand objects with multiple addresses in DST" ));
|
||||||
|
add( new ConvertToAtomic ("convert to atomic rules" ));
|
||||||
|
add( new DetectShadowing ("Detect shadowing" ));
|
||||||
|
add( new simplePrintProgress ( ));
|
||||||
|
|
||||||
|
runRuleProcessors();
|
||||||
|
deleteRuleProcessors();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
add( new Begin (" Start processing rules" ));
|
||||||
|
add( new printTotalNumberOfRules ( ));
|
||||||
|
add( new RejectAction ("check for action 'Reject'" ));
|
||||||
|
|
||||||
|
add( new recursiveGroupsInSrc( "check for recursive groups in SRC" ));
|
||||||
|
add( new recursiveGroupsInDst( "check for recursive groups in DST" ));
|
||||||
|
add( new recursiveGroupsInSrv( "check for recursive groups in SRV" ));
|
||||||
|
|
||||||
|
add( new emptyGroupsInSrc( "check for empty groups in SRC" ));
|
||||||
|
add( new emptyGroupsInDst( "check for empty groups in DST" ));
|
||||||
|
add( new emptyGroupsInSrv( "check for empty groups in SRV" ));
|
||||||
|
|
||||||
|
add( new ExpandGroups ("expand groups" ));
|
||||||
|
add( new eliminateDuplicatesInSRC( "eliminate duplicates in SRC" ));
|
||||||
|
add( new eliminateDuplicatesInDST( "eliminate duplicates in DST" ));
|
||||||
|
add( new eliminateDuplicatesInSRV( "eliminate duplicates in SRV" ));
|
||||||
|
|
||||||
|
add( new processMultiAddressObjectsInSrc(
|
||||||
|
"process MultiAddress objects in Src"));
|
||||||
|
add( new processMultiAddressObjectsInDst(
|
||||||
|
"process MultiAddress objects in Dst"));
|
||||||
|
|
||||||
|
add( new ItfNegation( "process negation in Itf" ));
|
||||||
|
add( new InterfacePolicyRules(
|
||||||
|
"process interface policy rules and store interface ids"));
|
||||||
|
|
||||||
|
if ( fwopt->getBool("pix_assume_fw_part_of_any")) {
|
||||||
|
// add( new splitIfSrcAny( "split rule if src is any" ));
|
||||||
|
add( new splitIfDstAny( "split rule if dst is any" ));
|
||||||
|
}
|
||||||
|
|
||||||
|
add( new splitIfSrcMatchesFw ("split rule if Src matches FW" ));
|
||||||
|
add( new splitIfDstMatchesFw ("split rule if Dst matches FW" ));
|
||||||
|
|
||||||
|
// if ( !outbound_acl_supported )
|
||||||
|
// add( new fillDirection_v6 ("determine directions" ));
|
||||||
|
|
||||||
|
// if ( fwopt->getBool("pix_replace_natted_objects"))
|
||||||
|
// add( new replaceNATtedObjects ("replace objects in DST that are TDst in DNAT translations" ));
|
||||||
|
|
||||||
|
add( new telnetToFirewall(
|
||||||
|
"separate rules controlling telnet to firewall"));
|
||||||
|
add( new sshToFirewall("separate rules controlling ssh to firewall" ));
|
||||||
|
add( new splitServices("split rules with different protocols" ));
|
||||||
|
add( new PrepareForICMPCmd("prepare for icmp command" ));
|
||||||
|
|
||||||
|
add( new replaceFWinSRCInterfacePolicy(
|
||||||
|
"replace fw with its interface in SRC in interface policy rules"));
|
||||||
|
add( new replaceFWinDSTInterfacePolicy(
|
||||||
|
"replace fw with its interface in DST in interface policy rules"));
|
||||||
|
|
||||||
|
add( new ExpandMultipleAddressesInSRC(
|
||||||
|
"expand objects with multiple addresses in SRC" ));
|
||||||
|
add( new MACFiltering("check for MAC address filtering" ));
|
||||||
|
add( new splitByNetworkZonesForSrc(
|
||||||
|
"split rule if objects in Src belong to different network zones " ));
|
||||||
|
add( new replaceFWinDSTPolicy(
|
||||||
|
"replace fw with its interface in DST in global policy rules"));
|
||||||
|
|
||||||
|
add( new ExpandMultipleAddressesInDST(
|
||||||
|
"expand objects with multiple addresses in DST" ));
|
||||||
|
add( new MACFiltering("check for MAC address filtering" ));
|
||||||
|
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" ));
|
||||||
|
|
||||||
|
if (outbound_acl_supported )
|
||||||
|
{
|
||||||
|
add( new setInterfaceAndDirectionBySrc(
|
||||||
|
"Set interface and direction for rules with interface 'all' using SRC; v7"));
|
||||||
|
add( new setInterfaceAndDirectionByDst(
|
||||||
|
"Set interface and direction for rules with interface 'all' using DST; v7"));
|
||||||
|
add(new setInterfaceAndDirectionIfInterfaceSet(
|
||||||
|
"Set direction for rules with interface not 'all'; v7"));
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
add( new SplitDirection_v6("split rules with direction 'both'" ));
|
||||||
|
// add( new assignRuleToInterface ("assign rules to interfaces" ));
|
||||||
|
add( new EmulateOutboundACL_v6("emulate outbound ACL" ));
|
||||||
|
add( new assignRuleToInterface_v6("assign rules to interfaces" ));
|
||||||
|
add( new InterfaceAndDirection_v6(
|
||||||
|
"check for combinations of interface and direction"));
|
||||||
|
}
|
||||||
|
|
||||||
|
add( new specialCaseWithDynInterface(
|
||||||
|
"check for a special cases with dynamic interface" ));
|
||||||
|
|
||||||
|
add( new SplitSRCForICMPCmd( "split SRC for icmp commands" ));
|
||||||
|
|
||||||
|
if ( fwopt->getBool("pix_replace_natted_objects"))
|
||||||
|
add( new replaceNATtedObjects(
|
||||||
|
"replace objects in DST that are TDst in DNAT translations"));
|
||||||
|
|
||||||
|
|
||||||
|
if (outbound_acl_supported )
|
||||||
|
// first arg is false because we are not using
|
||||||
|
// "ip access-list" for PIX.
|
||||||
|
add( new pickACL( false, "assign ACLs for v7" ));
|
||||||
|
else
|
||||||
|
add( new pickACL_v6( "assign ACLs for v6" ));
|
||||||
|
|
||||||
|
add( new SpecialServices( "check for special services" ));
|
||||||
|
add( new checkForZeroAddr( "check for zero addresses" ));
|
||||||
|
add( new checkVersionAndDynamicInterface(
|
||||||
|
"check for dynamic interfaces in policy rule and verify version of PIX OS"));
|
||||||
|
|
||||||
|
add( new splitIfTelnetSSHICMPtoFw(
|
||||||
|
"split rule if there are multiple objects in src and it controlls access to the firewall"));
|
||||||
|
|
||||||
|
/* remove redundant objects only after all splits has been
|
||||||
|
* done, right before object groups are created
|
||||||
|
*/
|
||||||
|
add( new removeRedundantAddressesFromSrc(
|
||||||
|
"remove redundant addresses from Src"));
|
||||||
|
add( new removeRedundantAddressesFromDst(
|
||||||
|
"remove redundant addresses from Dst"));
|
||||||
|
// add( new AvoidObjectGroup("avoid object groups for certain cases"));
|
||||||
|
add( new CreateObjectGroupsForSrc("create object groups for Src"));
|
||||||
|
add( new CreateObjectGroupsForDst("create object groups for Dst"));
|
||||||
|
add( new CreateObjectGroupsForSrv("create object groups for Srv"));
|
||||||
|
|
||||||
|
add( new simplePrintProgress());
|
||||||
|
|
||||||
|
add( new createNewCompilerPass("Creating object groups and ACLs ..."));
|
||||||
|
|
||||||
|
add( new PrintObjectGroupsAndClearCommands(
|
||||||
|
"Clear ACLs and generate code for object groups"));
|
||||||
|
add( new PrintRule("generate code for ACLs"));
|
||||||
|
add( new simplePrintProgress());
|
||||||
|
|
||||||
|
/*
|
||||||
|
if ( fw->getOptionsObject()->getBool("pix_check_rule_shadowing"))
|
||||||
|
{
|
||||||
|
add( new createNewCompilerPass (" Detecting rule shadowing ..." ));
|
||||||
|
add( new ExpandGroups ("expand groups" ));
|
||||||
|
add( new ConvertToAtomic ("convert to atomic rules" ));
|
||||||
|
add( new DetectShadowing ("Detect shadowing" ));
|
||||||
|
add( new simplePrintProgress ( ));
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
runRuleProcessors();
|
||||||
|
|
||||||
|
} catch (FWException &ex) {
|
||||||
|
error(ex.toString());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string PolicyCompiler_pix::printAccessGroupCmd(ciscoACL *acl)
|
||||||
|
{
|
||||||
|
string dir;
|
||||||
|
if (acl->direction()=="in" || acl->direction()=="Inbound") dir="in";
|
||||||
|
if (acl->direction()=="out" || acl->direction()=="Outbound") dir="out";
|
||||||
|
return string("access-group ") + acl->workName() +
|
||||||
|
" " + dir +
|
||||||
|
" interface " + acl->getInterface()->getLabel() + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolicyCompiler_pix::epilog()
|
||||||
|
{
|
||||||
|
output << endl;
|
||||||
|
if (resetinbound) output << "service resetinbound" << endl;
|
||||||
|
|
||||||
|
output << endl;
|
||||||
|
if (fw->getStr("platform")=="fwsm" && fw->getOptionsObject()->getBool("pix_use_manual_commit"))
|
||||||
|
{
|
||||||
|
output << "access-list commit" << endl;
|
||||||
|
output << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (map<string,ciscoACL*>::iterator i=acls.begin(); i!=acls.end(); ++i)
|
||||||
|
{
|
||||||
|
ciscoACL *acl=(*i).second;
|
||||||
|
if (acl->size()!=0) output << printAccessGroupCmd(acl);
|
||||||
|
}
|
||||||
|
output << endl;
|
||||||
|
|
||||||
|
if ( fw->getOptionsObject()->getBool("pix_regroup_commands"))
|
||||||
|
{
|
||||||
|
cout << " Regrouping commands \n" << flush;
|
||||||
|
regroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,327 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2002 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: PolicyCompiler_pix.h,v 1.1 2008/03/06 06:49:00 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
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __POLICYCOMPILER_PIX_HH
|
||||||
|
#define __POLICYCOMPILER_PIX_HH
|
||||||
|
|
||||||
|
#include <fwbuilder/libfwbuilder-config.h>
|
||||||
|
#include "PIXObjectGroup.h"
|
||||||
|
|
||||||
|
#include "fwcompiler/PolicyCompiler.h"
|
||||||
|
#include "fwbuilder/RuleElement.h"
|
||||||
|
|
||||||
|
#include "Helper.h"
|
||||||
|
#include "ACL.h"
|
||||||
|
#include "PolicyCompiler_cisco.h"
|
||||||
|
|
||||||
|
namespace libfwbuilder {
|
||||||
|
class IPService;
|
||||||
|
class ICMPService;
|
||||||
|
class TCPService;
|
||||||
|
class UDPService;
|
||||||
|
class RuleElementSrc;
|
||||||
|
class RuleElementDst;
|
||||||
|
class RuleElementSrv;
|
||||||
|
class Group;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace fwcompiler {
|
||||||
|
|
||||||
|
class NATCompiler_pix;
|
||||||
|
|
||||||
|
class PolicyCompiler_pix : public PolicyCompiler_cisco {
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dynamic interfaces can be used in policy rules only in v6.3 and later
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
friend class checkVersionAndDynamicInterface;
|
||||||
|
class checkVersionAndDynamicInterface : public PolicyRuleProcessor
|
||||||
|
{
|
||||||
|
bool findDynamicInterface(libfwbuilder::PolicyRule *rule,
|
||||||
|
libfwbuilder::RuleElement *re);
|
||||||
|
public:
|
||||||
|
checkVersionAndDynamicInterface(const std::string &name) : PolicyRuleProcessor(name) {}
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*************************************************************************
|
||||||
|
*
|
||||||
|
* the following rule processors are intended for PIX < 7.0
|
||||||
|
* the code is in the module PolicyCompiler_pix_v6_acls.cpp
|
||||||
|
*
|
||||||
|
*************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* verifies combination of interface and direction and
|
||||||
|
* fills interface and direction. After this predicate it
|
||||||
|
* is guaranteed that both interface and direction have
|
||||||
|
* some value. In certain situations interface ID may be
|
||||||
|
* set to "nil" though (e.g. global policy rules).
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( InterfaceAndDirection_v6 );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if interface has not been defined (this is global policy
|
||||||
|
* rule), then multiply the rule for each interface and set
|
||||||
|
* direction to "Inbound"
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( assignRuleToInterface_v6 );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* split rules with direction "both".
|
||||||
|
* TODO: This is used in OpenBSD pf. Move to class PolicyCompiler
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( SplitDirection_v6 );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* in PIX, ACLs are always applied on interface and direction
|
||||||
|
* can only be "inbound". We emulate outbound ACLs though.
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( EmulateOutboundACL_v6 );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* determine acl rules should belong to
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( pickACL_v6 );
|
||||||
|
friend class PolicyCompiler_pix::pickACL_v6;
|
||||||
|
|
||||||
|
/*
|
||||||
|
*************************************************************************
|
||||||
|
*
|
||||||
|
* end of module PolicyCompiler_pix_v6_acls.cpp
|
||||||
|
*
|
||||||
|
*************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
*************************************************************************
|
||||||
|
*
|
||||||
|
* rule processors intended to manage ACLs for PIX < 7.0 are inherited
|
||||||
|
* from PolicyCompiler_cisco.
|
||||||
|
* The code is in the module PolicyCompiler_cisco_acls.cpp
|
||||||
|
*
|
||||||
|
* The processors assume that all objects in src and dst
|
||||||
|
* belong to the same network zone (respectively)
|
||||||
|
*
|
||||||
|
* All these rule processors assume outbound ACLs are supported.
|
||||||
|
* Check corresponding capability flag and do not include these
|
||||||
|
* processors in the processors chain in pix.cpp if outbound acls
|
||||||
|
* are not supported.
|
||||||
|
*
|
||||||
|
*************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this processor checks for the services which require
|
||||||
|
* special treatment. Some of these will be checking for
|
||||||
|
* source or destination object as well because special
|
||||||
|
* command may need to be generated in case source or
|
||||||
|
* destination is a firewall itself. Therefore this processor
|
||||||
|
* should be called after converting to atomic rules, but
|
||||||
|
* before interface addresses in source and destination are
|
||||||
|
* expanded.
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( SpecialServices );
|
||||||
|
friend class PolicyCompiler_pix::SpecialServices;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sets boolean flag icmp_cmd to be able to generate command
|
||||||
|
* "icmp" instead of "access-list" later. Call this processor
|
||||||
|
* after SplitServices and splitIfDstMatchesFw
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( PrepareForICMPCmd );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* splits SRC if this is icmp_cmd rule
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( SplitSRCForICMPCmd );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* to implement action "Reject" add command "service resetinbound"
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( RejectAction );
|
||||||
|
friend class PolicyCompiler_pix::RejectAction;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this processor replaces objects in dst for which we have
|
||||||
|
* DNAT rule in a NAT policy. Call _after_ telnetToFirewall,
|
||||||
|
* sshToFirewall and PrepareForICMPCmd
|
||||||
|
*/
|
||||||
|
class replaceNATtedObjects : public PolicyRuleProcessor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
replaceNATtedObjects(const std::string &n):PolicyRuleProcessor(n) {}
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
friend class PolicyCompiler_pix::replaceNATtedObjects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* can not use object-group in "icmp", "telnet" and "ssh" commands
|
||||||
|
*/
|
||||||
|
DECLARE_POLICY_RULE_PROCESSOR( splitIfTelnetSSHICMPtoFw );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this processor creates PIX-specific object groups
|
||||||
|
* (PIX CLI command "object-group") for rules with
|
||||||
|
* more than one object in src or dst or srv
|
||||||
|
*/
|
||||||
|
class CreateObjectGroups : public PolicyRuleProcessor
|
||||||
|
{
|
||||||
|
std::string re_type;
|
||||||
|
std::string name_suffix;
|
||||||
|
PIXGroup* findObjectGroup(libfwbuilder::RuleElement *re);
|
||||||
|
public:
|
||||||
|
CreateObjectGroups(const std::string &name,
|
||||||
|
const std::string &_ns,
|
||||||
|
const std::string &_type) :
|
||||||
|
PolicyRuleProcessor(name) {re_type=_type; name_suffix=_ns; }
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
friend class PolicyCompiler_pix::CreateObjectGroups;
|
||||||
|
|
||||||
|
class CreateObjectGroupsForSrc : public CreateObjectGroups
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CreateObjectGroupsForSrc(const std::string &n):
|
||||||
|
CreateObjectGroups(n,"src",libfwbuilder::RuleElementSrc::TYPENAME) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CreateObjectGroupsForDst : public CreateObjectGroups
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CreateObjectGroupsForDst(const std::string &n):
|
||||||
|
CreateObjectGroups(n,"dst",libfwbuilder::RuleElementDst::TYPENAME) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CreateObjectGroupsForSrv : public CreateObjectGroups
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CreateObjectGroupsForSrv(const std::string &n):
|
||||||
|
CreateObjectGroups(n,"srv",libfwbuilder::RuleElementSrv::TYPENAME) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this processor accumulates all rules fed to it by previous
|
||||||
|
* * processors, then prints PIX commands to clear
|
||||||
|
* access-lists, object groups, icmp, ssh, telnet and prints
|
||||||
|
* all object groups, then feeds all rules to the next
|
||||||
|
* processor. Usually this processor is in chain right
|
||||||
|
* before PrintRules.
|
||||||
|
*
|
||||||
|
* We use this processor to print "clear" commands because
|
||||||
|
* they need to be generated when all access lists have been
|
||||||
|
* created but before they are printed.
|
||||||
|
*/
|
||||||
|
class PrintObjectGroupsAndClearCommands : public PolicyRuleProcessor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PrintObjectGroupsAndClearCommands(const std::string &n) : PolicyRuleProcessor(n) {}
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
friend class PolicyCompiler_pix::PrintObjectGroupsAndClearCommands;
|
||||||
|
|
||||||
|
class AvoidObjectGroup : public PolicyRuleProcessor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AvoidObjectGroup(const std::string &n) : PolicyRuleProcessor(n) {}
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
friend class PolicyCompiler_pix::AvoidObjectGroup;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this processor prints single policy rule, assuming all
|
||||||
|
* groups have been expanded, so source, destination and
|
||||||
|
* service hold exactly one object each, and this object is
|
||||||
|
* not a group. Negation should also have been taken care of
|
||||||
|
* before this method is called.
|
||||||
|
*/
|
||||||
|
class PrintRule : public PolicyRuleProcessor
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::string current_rule_label1;
|
||||||
|
std::map<std::string,std::string> current_rule_label2;
|
||||||
|
std::list<std::string> seen_icmp_commands;
|
||||||
|
int aclLineCounter;
|
||||||
|
|
||||||
|
std::string _printSingleSSHTelnetCommand(int port,
|
||||||
|
libfwbuilder::Address *a,
|
||||||
|
const std::string &interfaceLabel);
|
||||||
|
std::string _printSrcService(libfwbuilder::Service *srv);
|
||||||
|
std::string _printDstService(libfwbuilder::Service *srv);
|
||||||
|
std::string _printAddr(libfwbuilder::Address *o);
|
||||||
|
std::string _printAction(libfwbuilder::PolicyRule *r);
|
||||||
|
std::string _printACL(libfwbuilder::PolicyRule *r);
|
||||||
|
std::string _printSSHTelnetCommand(libfwbuilder::PolicyRule *r);
|
||||||
|
std::string _printICMPCommand(libfwbuilder::PolicyRule *r);
|
||||||
|
std::string _printLog(libfwbuilder::PolicyRule *r);
|
||||||
|
bool suppressDuplicateICMPCommands(const std::string &cmd);
|
||||||
|
|
||||||
|
public:
|
||||||
|
PrintRule(const std::string &name) : PolicyRuleProcessor(name) { aclLineCounter=0; }
|
||||||
|
virtual bool processNext();
|
||||||
|
};
|
||||||
|
friend class PolicyCompiler_pix::PrintRule;
|
||||||
|
|
||||||
|
|
||||||
|
bool resetinbound;
|
||||||
|
bool fragguard;
|
||||||
|
|
||||||
|
// storage for object groups created to be used with PIX command object-group
|
||||||
|
libfwbuilder::Group *object_groups;
|
||||||
|
|
||||||
|
NATCompiler_pix *natcmp;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual std::string myPlatformName();
|
||||||
|
std::string printAccessGroupCmd(ciscoACL *acl);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
PolicyCompiler_pix(libfwbuilder::FWObjectDatabase *_db,
|
||||||
|
const std::string &fwname,
|
||||||
|
fwcompiler::OSConfigurator *_oscnf,
|
||||||
|
NATCompiler_pix *_natcmp);
|
||||||
|
virtual ~PolicyCompiler_pix() {}
|
||||||
|
|
||||||
|
virtual int prolog();
|
||||||
|
virtual void compile();
|
||||||
|
virtual void epilog();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,361 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2002 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: PolicyCompiler_pix_v6_acls.cpp,v 1.1 2008/03/06 06:49:00 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
|
||||||
|
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
string interface_id = rule->getInterfaceId();
|
||||||
|
|
||||||
|
if (rule->getDirection()==PolicyRule::Undefined)
|
||||||
|
rule->setDirection( PolicyRule::Both );
|
||||||
|
|
||||||
|
if (interface_id.empty() && rule->getDirection()==PolicyRule::Both)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (interface_id.empty() && !icmp_cmd && !ssh_telnet_cmd && (
|
||||||
|
rule->getDirection()==PolicyRule::Inbound ||
|
||||||
|
rule->getDirection()==PolicyRule::Outbound)
|
||||||
|
) compiler->abort(string("Direction set without interface in rule ")+rule->getLabel());
|
||||||
|
|
||||||
|
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;
|
||||||
|
Interface *rule_iface = compiler->getCachedFwInterface(rule->getInterfaceId());
|
||||||
|
|
||||||
|
if (rule->getDirection()==PolicyRule::Both)
|
||||||
|
{
|
||||||
|
if (rule_iface!=NULL)
|
||||||
|
{
|
||||||
|
PolicyRule *r= PolicyRule::cast(
|
||||||
|
compiler->dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
compiler->temp_ruleset->add(r);
|
||||||
|
r->duplicate(rule);
|
||||||
|
r->setDirection(PolicyRule::Inbound);
|
||||||
|
tmp_queue.push_back(r);
|
||||||
|
|
||||||
|
r= PolicyRule::cast(
|
||||||
|
compiler->dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
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;
|
||||||
|
Interface *rule_iface = compiler->getCachedFwInterface(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())
|
||||||
|
{
|
||||||
|
string 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
|
||||||
|
{
|
||||||
|
string 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= PolicyRule::cast(
|
||||||
|
compiler->dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
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(str.str());
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
compiler->abort("Outbound ACLs are not supported and emulation is not activated: Rule "+rule->getLabel());
|
||||||
|
} 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()=="")
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (! src->isAny() )
|
||||||
|
{
|
||||||
|
Address *a=compiler->getFirstSrc(rule);
|
||||||
|
string 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))
|
||||||
|
{
|
||||||
|
string 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->getByType(Interface::TYPENAME);
|
||||||
|
for (list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i)
|
||||||
|
{
|
||||||
|
PolicyRule *r= PolicyRule::cast(
|
||||||
|
compiler->dbcopy->create(PolicyRule::TYPENAME) );
|
||||||
|
compiler->temp_ruleset->add(r);
|
||||||
|
|
||||||
|
r->duplicate(rule);
|
||||||
|
r->setInterfaceId((*i)->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(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 = compiler->getCachedFwInterface(rule->getInterfaceId());
|
||||||
|
if(rule_iface==NULL)
|
||||||
|
{
|
||||||
|
compiler->abort("Missing interface assignment for rule "+rule->getLabel());
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,688 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2002 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: PolicyCompiler_pix_writers.cpp,v 1.1 2008/03/06 06:49:00 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_pix.h"
|
||||||
|
#include "PIXObjectGroup.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_pix::PrintObjectGroupsAndClearCommands::processNext()
|
||||||
|
{
|
||||||
|
PolicyCompiler_pix *pix_comp=dynamic_cast<PolicyCompiler_pix*>(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+"/pix_commands/clear_acl");
|
||||||
|
string clearOGcmd = Resources::platform_res[platform]->getResourceStr(
|
||||||
|
string("/FWBuilderResources/Target/options/")+
|
||||||
|
"version_"+vers+"/pix_commands/clear_og");
|
||||||
|
string clearICMPcmd = Resources::platform_res[platform]->getResourceStr(
|
||||||
|
string("/FWBuilderResources/Target/options/")+
|
||||||
|
"version_"+vers+"/pix_commands/clear_icmp");
|
||||||
|
string clearTelnetcmd = Resources::platform_res[platform]->getResourceStr(
|
||||||
|
string("/FWBuilderResources/Target/options/")+
|
||||||
|
"version_"+vers+"/pix_commands/clear_telnet");
|
||||||
|
string clearSSHcmd = Resources::platform_res[platform]->getResourceStr(
|
||||||
|
string("/FWBuilderResources/Target/options/")+
|
||||||
|
"version_"+vers+"/pix_commands/clear_ssh");
|
||||||
|
|
||||||
|
|
||||||
|
slurp();
|
||||||
|
if (tmp_queue.size()==0) return false;
|
||||||
|
|
||||||
|
if ( compiler->fw->getOptionsObject()->getBool("pix_acl_basic") )
|
||||||
|
{
|
||||||
|
compiler->output << clearACLcmd << endl;
|
||||||
|
compiler->output << clearOGcmd << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (compiler->fw->getOptionsObject()->getBool("pix_acl_substitution"))
|
||||||
|
{
|
||||||
|
for (map<string,ciscoACL*>::iterator i=pix_comp->acls.begin();
|
||||||
|
i!=pix_comp->acls.end(); ++i)
|
||||||
|
{
|
||||||
|
ciscoACL *acl=(*i).second;
|
||||||
|
compiler->output << clearACLcmd << " " << acl->workName() << endl;
|
||||||
|
}
|
||||||
|
compiler->output << clearOGcmd << endl;
|
||||||
|
compiler->output << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !compiler->fw->getOptionsObject()->getBool("pix_acl_no_clear") )
|
||||||
|
{
|
||||||
|
compiler->output << clearICMPcmd << endl;
|
||||||
|
compiler->output << clearTelnetcmd << endl;
|
||||||
|
compiler->output << clearSSHcmd << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (FWObject::iterator i=pix_comp->object_groups->begin();
|
||||||
|
i!=pix_comp->object_groups->end(); ++i)
|
||||||
|
{
|
||||||
|
PIXGroup *og=dynamic_cast<PIXGroup*>(*i);
|
||||||
|
assert(og!=NULL);
|
||||||
|
|
||||||
|
if (og->size()==0) continue;
|
||||||
|
|
||||||
|
pix_comp->output << endl;
|
||||||
|
|
||||||
|
switch (og->getPIXGroupType())
|
||||||
|
{
|
||||||
|
case NETWORK:
|
||||||
|
pix_comp->output << "object-group network "
|
||||||
|
<< og->getName() << endl;
|
||||||
|
break;
|
||||||
|
case PROTO:
|
||||||
|
pix_comp->output << "object-group protocol "
|
||||||
|
<< og->getName() << endl;
|
||||||
|
break;
|
||||||
|
case ICMP_TYPE:
|
||||||
|
pix_comp->output << "object-group icmp-type "
|
||||||
|
<< og->getName() << endl;
|
||||||
|
break;
|
||||||
|
case TCP_SERVICE:
|
||||||
|
pix_comp->output << "object-group service "
|
||||||
|
<< og->getName() << " tcp" << endl;
|
||||||
|
break;
|
||||||
|
case UDP_SERVICE:
|
||||||
|
pix_comp->output << "object-group service "
|
||||||
|
<< og->getName() << " udp" << endl;
|
||||||
|
break;
|
||||||
|
default: compiler->abort("Unknown object group");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (FWObject::iterator i1=og->begin(); i1!=og->end(); ++i1)
|
||||||
|
{
|
||||||
|
FWObject *o = *i1;
|
||||||
|
FWObject *obj = o;
|
||||||
|
if (FWReference::cast(o)!=NULL) obj=FWReference::cast(o)->getPointer();
|
||||||
|
|
||||||
|
switch (og->getPIXGroupType())
|
||||||
|
{
|
||||||
|
case NETWORK:
|
||||||
|
{
|
||||||
|
Address *a=Address::cast(obj);
|
||||||
|
assert(a!=NULL);
|
||||||
|
IPAddress addr=a->getAddress();
|
||||||
|
pix_comp->output << " network-object ";
|
||||||
|
if (Network::cast(obj)!=NULL) {
|
||||||
|
Netmask mask=a->getNetmask();
|
||||||
|
pix_comp->output << addr.toString() << " ";
|
||||||
|
pix_comp->output << mask.toString() << " ";
|
||||||
|
} else {
|
||||||
|
pix_comp->output << " host ";
|
||||||
|
pix_comp->output << addr.toString() << " ";
|
||||||
|
}
|
||||||
|
pix_comp->output << endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PROTO:
|
||||||
|
{
|
||||||
|
pix_comp->output << " protocol-object ";
|
||||||
|
Service *s=Service::cast(obj);
|
||||||
|
assert(s!=NULL);
|
||||||
|
pix_comp->output << s->getProtocolName();
|
||||||
|
pix_comp->output << endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ICMP_TYPE:
|
||||||
|
{
|
||||||
|
pix_comp->output << " icmp-object ";
|
||||||
|
ICMPService *s=ICMPService::cast(obj);
|
||||||
|
assert(s!=NULL);
|
||||||
|
if ( s->getInt("type")== -1)
|
||||||
|
pix_comp->output << "any";
|
||||||
|
else
|
||||||
|
pix_comp->output << s->getInt("type");
|
||||||
|
pix_comp->output << endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TCP_SERVICE:
|
||||||
|
case UDP_SERVICE:
|
||||||
|
{
|
||||||
|
pix_comp->output << " port-object ";
|
||||||
|
Service *s=Service::cast(obj);
|
||||||
|
assert(s!=NULL);
|
||||||
|
|
||||||
|
int rs=s->getInt("dst_range_start");
|
||||||
|
int re=s->getInt("dst_range_end");
|
||||||
|
|
||||||
|
if (rs<0) rs=0;
|
||||||
|
if (re<0) re=0;
|
||||||
|
|
||||||
|
if (rs>0 || re>0) {
|
||||||
|
if (rs==re) compiler->output << "eq " << rs;
|
||||||
|
else compiler->output << "range " << rs << " " << re;
|
||||||
|
}
|
||||||
|
else compiler->output << "range 0 65535";
|
||||||
|
pix_comp->output << endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
compiler->abort("Unknown object group");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pix_comp->output << " exit" << endl << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string PolicyCompiler_pix::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_pix::PrintRule::_printACL(PolicyRule *rule)
|
||||||
|
{
|
||||||
|
// PolicyCompiler_pix *pix_comp=dynamic_cast<PolicyCompiler_pix*>(compiler);
|
||||||
|
|
||||||
|
string acl_name=rule->getStr("acl");
|
||||||
|
assert (acl_name!="");
|
||||||
|
|
||||||
|
return acl_name+" ";
|
||||||
|
}
|
||||||
|
|
||||||
|
string PolicyCompiler_pix::PrintRule::_printLog(PolicyRule *rule)
|
||||||
|
{
|
||||||
|
string platform=compiler->fw->getStr("platform");
|
||||||
|
string vers=compiler->fw->getStr("version");
|
||||||
|
if (platform=="pix" && (vers=="6.1" || vers=="6.2")) return "";
|
||||||
|
|
||||||
|
// PolicyCompiler_pix *pix_comp=dynamic_cast<PolicyCompiler_pix*>(compiler);
|
||||||
|
FWOptions *ruleopt =rule->getOptionsObject();
|
||||||
|
ostringstream str;
|
||||||
|
|
||||||
|
if (ruleopt->getBool("disable_logging_for_this_rule"))
|
||||||
|
return "log disable ";
|
||||||
|
|
||||||
|
if (rule->getLogging())
|
||||||
|
{
|
||||||
|
string level=ruleopt->getStr("log_level");
|
||||||
|
int logint=ruleopt->getInt("log_interval");
|
||||||
|
/*
|
||||||
|
* PIX always adds logging interval in "show * access-list" command,
|
||||||
|
* so we should always add it, too. Otherwise ACL lines look
|
||||||
|
* different when diff is generated.
|
||||||
|
*/
|
||||||
|
if (logint<=0)
|
||||||
|
logint=Resources::platform_res[platform]->getResourceInt(
|
||||||
|
string("/FWBuilderResources/Target/options/")+
|
||||||
|
"version_"+compiler->fw->getStr("version")+
|
||||||
|
"/pix_default_logint");
|
||||||
|
|
||||||
|
if (level.empty()) level= compiler->fw->getOptionsObject()->getStr("pix_logging_trap_level");
|
||||||
|
|
||||||
|
if (!level.empty())
|
||||||
|
{
|
||||||
|
if (level=="alert") level="1";
|
||||||
|
if (level=="crit") level="2";
|
||||||
|
if (level=="error") level="3";
|
||||||
|
if (level=="warning") level="4";
|
||||||
|
if (level=="notice") level="5";
|
||||||
|
if (level=="info") level="6";
|
||||||
|
if (level=="debug") level="7";
|
||||||
|
str << "log " << level << " ";
|
||||||
|
if (logint>0 || platform=="pix") // can't use "interval 0" on fwsm
|
||||||
|
str << "interval " << logint << " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
string PolicyCompiler_pix::PrintRule::_printSrcService(libfwbuilder::Service *srv)
|
||||||
|
{
|
||||||
|
ostringstream str;
|
||||||
|
|
||||||
|
if (TCPService::isA(srv) || UDPService::isA(srv))
|
||||||
|
{
|
||||||
|
int rs=srv->getInt("src_range_start");
|
||||||
|
int re=srv->getInt("src_range_end");
|
||||||
|
|
||||||
|
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_pix::PrintRule::_printDstService(libfwbuilder::Service *srv)
|
||||||
|
{
|
||||||
|
ostringstream str;
|
||||||
|
|
||||||
|
if (TCPService::isA(srv) || UDPService::isA(srv)) {
|
||||||
|
int rs=srv->getInt("dst_range_start");
|
||||||
|
int re=srv->getInt("dst_range_end");
|
||||||
|
|
||||||
|
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 (ICMPService::isA(srv) && srv->getInt("type")!=-1)
|
||||||
|
str << srv->getStr("type") << " ";
|
||||||
|
return str.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
string PolicyCompiler_pix::PrintRule::_printAddr(libfwbuilder::Address *o)
|
||||||
|
{
|
||||||
|
ostringstream str;
|
||||||
|
|
||||||
|
IPAddress srcaddr=o->getAddress();
|
||||||
|
Netmask srcmask=o->getNetmask();
|
||||||
|
|
||||||
|
if (Interface::cast(o)!=NULL)
|
||||||
|
{
|
||||||
|
Interface *interface_=Interface::cast(o);
|
||||||
|
if (interface_->isDyn())
|
||||||
|
{
|
||||||
|
return string("interface ") + interface_->getLabel() + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
srcmask=Netmask("255.255.255.255");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IPv4::cast(o)!=NULL)
|
||||||
|
srcmask=Netmask("255.255.255.255");
|
||||||
|
|
||||||
|
|
||||||
|
if (srcaddr.toString()=="0.0.0.0" && srcmask.toString()=="0.0.0.0")
|
||||||
|
{
|
||||||
|
str << "any ";
|
||||||
|
} else {
|
||||||
|
if (srcmask.toString()=="255.255.255.255")
|
||||||
|
{
|
||||||
|
str << "host " << srcaddr.toString() << " ";
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
str << srcaddr.toString() << " ";
|
||||||
|
str << srcmask.toString() << " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolicyCompiler_pix::PrintRule::suppressDuplicateICMPCommands(const string &cmd)
|
||||||
|
{
|
||||||
|
list<string>::iterator i;
|
||||||
|
i=std::find(seen_icmp_commands.begin(),seen_icmp_commands.end(),cmd);
|
||||||
|
if (i!=seen_icmp_commands.end()) return true;
|
||||||
|
seen_icmp_commands.push_back(cmd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string PolicyCompiler_pix::PrintRule::_printICMPCommand(PolicyRule *rule)
|
||||||
|
{
|
||||||
|
ostringstream str;
|
||||||
|
|
||||||
|
Address *src =compiler->getFirstSrc(rule);
|
||||||
|
|
||||||
|
RuleElementSrv *srvrel=rule->getSrv();
|
||||||
|
FWObject *srv=srvrel->front();
|
||||||
|
if (FWReference::cast(srv)!=NULL) srv=FWReference::cast(srv)->getPointer();
|
||||||
|
|
||||||
|
Interface *rule_iface = compiler->getCachedFwInterface(rule->getInterfaceId());
|
||||||
|
assert(rule_iface);
|
||||||
|
|
||||||
|
if ( PIXGroup::cast(srv)!=NULL &&
|
||||||
|
PIXGroup::cast(srv)->getPIXGroupType()==ICMP_TYPE)
|
||||||
|
{
|
||||||
|
for (FWObject::iterator i1=srv->begin(); i1!=srv->end(); ++i1)
|
||||||
|
{
|
||||||
|
FWObject *o = *i1;
|
||||||
|
FWObject *obj = o;
|
||||||
|
if (FWReference::cast(o)!=NULL) obj=FWReference::cast(o)->getPointer();
|
||||||
|
|
||||||
|
ICMPService *s=ICMPService::cast(obj);
|
||||||
|
assert(s!=NULL);
|
||||||
|
|
||||||
|
ostringstream str1;
|
||||||
|
str1 << "icmp ";
|
||||||
|
str1 << _printAction(rule);
|
||||||
|
str1 << _printAddr( src );
|
||||||
|
str1 << s->getStr("type");
|
||||||
|
str1 << " ";
|
||||||
|
str1 << rule_iface->getLabel();
|
||||||
|
str1 << endl;
|
||||||
|
|
||||||
|
if ( ! suppressDuplicateICMPCommands(str1.str())) str << str1.str();
|
||||||
|
}
|
||||||
|
return str.str();
|
||||||
|
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
str << "icmp ";
|
||||||
|
str << _printAction(rule);
|
||||||
|
str << _printAddr( src );
|
||||||
|
str << _printDstService( Service::cast(srv) );
|
||||||
|
str << " ";
|
||||||
|
str << rule_iface->getLabel();
|
||||||
|
str << endl;
|
||||||
|
if ( ! suppressDuplicateICMPCommands(str.str())) return str.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
string PolicyCompiler_pix::PrintRule::_printSSHTelnetCommand(PolicyRule *rule)
|
||||||
|
{
|
||||||
|
// Helper helper(this);
|
||||||
|
|
||||||
|
ostringstream str;
|
||||||
|
int port;
|
||||||
|
|
||||||
|
RuleElementSrc *rel=rule->getSrc();
|
||||||
|
Service *srv=compiler->getFirstSrv(rule);
|
||||||
|
|
||||||
|
Interface *rule_iface = compiler->getCachedFwInterface(rule->getInterfaceId());
|
||||||
|
assert(rule_iface);
|
||||||
|
|
||||||
|
port=srv->getInt("dst_range_start");
|
||||||
|
|
||||||
|
for (FWObject::iterator i=rel->begin(); i!=rel->end(); ++i)
|
||||||
|
{
|
||||||
|
FWObject *o = *i;
|
||||||
|
if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
|
||||||
|
// Address *a;
|
||||||
|
|
||||||
|
if (dynamic_cast<PIXGroup*>(o)!=NULL)
|
||||||
|
{
|
||||||
|
for (FWObject::iterator j=o->begin(); j!=o->end(); ++j)
|
||||||
|
{
|
||||||
|
FWObject *o1 = *j;
|
||||||
|
if (FWReference::cast(o1)!=NULL)
|
||||||
|
o1=FWReference::cast(o1)->getPointer();
|
||||||
|
Address *a=Address::cast(o1);
|
||||||
|
assert(a!=NULL);
|
||||||
|
str << _printSingleSSHTelnetCommand(port,a,rule_iface->getLabel());
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
Address *a=Address::cast(o);
|
||||||
|
assert(a!=NULL);
|
||||||
|
str << _printSingleSSHTelnetCommand(port,a,rule_iface->getLabel());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return str.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
string PolicyCompiler_pix::PrintRule::_printSingleSSHTelnetCommand(int port,
|
||||||
|
Address *a,
|
||||||
|
const string &interfaceLabel)
|
||||||
|
{
|
||||||
|
string res;
|
||||||
|
|
||||||
|
if (port==23)
|
||||||
|
{
|
||||||
|
res += "telnet ";
|
||||||
|
res += a->getAddress().toString() + " "
|
||||||
|
+ a->getNetmask().toString() + " "
|
||||||
|
+ interfaceLabel + "\n";
|
||||||
|
}
|
||||||
|
if (port==22)
|
||||||
|
{
|
||||||
|
res += "ssh ";
|
||||||
|
res += a->getAddress().toString() + " "
|
||||||
|
+ a->getNetmask().toString() + " "
|
||||||
|
+ interfaceLabel + "\n";
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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_pix::PrintRule::processNext()
|
||||||
|
{
|
||||||
|
PolicyCompiler_pix *pix_comp=dynamic_cast<PolicyCompiler_pix*>(compiler);
|
||||||
|
PolicyRule *rule=getNext(); if (rule==NULL) return false;
|
||||||
|
// FWOptions *ruleopt =rule->getOptionsObject();
|
||||||
|
bool write_comments= compiler->fw->getOptionsObject()->getBool("pix_include_comments");
|
||||||
|
|
||||||
|
tmp_queue.push_back(rule);
|
||||||
|
|
||||||
|
ostringstream comment;
|
||||||
|
|
||||||
|
string rl=rule->getLabel();
|
||||||
|
|
||||||
|
if (write_comments)
|
||||||
|
{
|
||||||
|
if (rl!=current_rule_label1)
|
||||||
|
{
|
||||||
|
comment << "! " << endl;
|
||||||
|
comment << "! Rule " << rl << endl;
|
||||||
|
|
||||||
|
string comm=rule->getComment();
|
||||||
|
string::size_type c1,c2;
|
||||||
|
c1=0;
|
||||||
|
while ( (c2=comm.find('\n',c1))!=string::npos ) {
|
||||||
|
comment << "! " << comm.substr(c1,c2-c1) << endl;
|
||||||
|
c1=c2+1;
|
||||||
|
}
|
||||||
|
comment << "! " << comm.substr(c1) << endl;
|
||||||
|
comment << "! " << endl;
|
||||||
|
|
||||||
|
current_rule_label1=rl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compiler->output << comment.str();
|
||||||
|
|
||||||
|
if (rule->getBool("icmp_cmd"))
|
||||||
|
{
|
||||||
|
compiler->output << _printICMPCommand(rule);
|
||||||
|
// need to generate access list command as well as icmp command
|
||||||
|
// in order to properly serve icmp through nat
|
||||||
|
// 04/21/06 --vk
|
||||||
|
// return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule->getBool("ssh_telnet_cmd"))
|
||||||
|
{
|
||||||
|
compiler->output << _printSSHTelnetCommand(rule);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
ostringstream aclstr;
|
||||||
|
|
||||||
|
string acl_name=rule->getStr("acl");
|
||||||
|
assert (acl_name!="");
|
||||||
|
|
||||||
|
ciscoACL *acl = pix_comp->acls[acl_name];
|
||||||
|
assert(acl!=NULL);
|
||||||
|
|
||||||
|
if (compiler->fw->getOptionsObject()->getBool("pix_use_acl_remarks"))
|
||||||
|
{
|
||||||
|
compiler->output << acl->addRemark( rule->getLabel() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Assemble ACL command in aclstr
|
||||||
|
*/
|
||||||
|
|
||||||
|
aclstr << _printAction(rule);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* processor splitServices guaranties that rule has services of
|
||||||
|
* the same type (that is, the same protocol, like all tcp, all
|
||||||
|
* udp, all icmp or all IP with the same protocol number). PIX can
|
||||||
|
* use object-group for protocol only if protocol numbers are
|
||||||
|
* different and these are not icmp/tcp/udp protocols. This means
|
||||||
|
* that because of processor splitServices we never use
|
||||||
|
* object-group in protocol part of ACL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
PIXGroup *pgsrv = PIXGroup::cast(srvobj);
|
||||||
|
PIXGroup *pgsrc = PIXGroup::cast(srcobj);
|
||||||
|
PIXGroup *pgdst = PIXGroup::cast(dstobj);
|
||||||
|
|
||||||
|
if ( pgsrv!=NULL && pgsrv->isServiceGroup())
|
||||||
|
aclstr << pgsrv->getSrvTypeName();
|
||||||
|
else
|
||||||
|
aclstr << Service::cast(srvobj)->getProtocolName();
|
||||||
|
|
||||||
|
aclstr << " ";
|
||||||
|
|
||||||
|
if ( pgsrc!=NULL && pgsrc->isObjectGroup())
|
||||||
|
{
|
||||||
|
aclstr << "object-group " << srcobj->getName();
|
||||||
|
aclstr << " ";
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
aclstr << _printAddr( compiler->getFirstSrc(rule) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pgsrv==NULL )
|
||||||
|
aclstr << _printSrcService( compiler->getFirstSrv(rule) );
|
||||||
|
|
||||||
|
if ( pgdst!=NULL && pgdst->isObjectGroup())
|
||||||
|
{
|
||||||
|
aclstr << "object-group " << dstobj->getName();
|
||||||
|
aclstr << " ";
|
||||||
|
} else
|
||||||
|
aclstr << _printAddr( compiler->getFirstDst(rule) );
|
||||||
|
|
||||||
|
|
||||||
|
if ( pgsrv!=NULL )
|
||||||
|
{
|
||||||
|
aclstr << "object-group " << srvobj->getName();
|
||||||
|
aclstr << " ";
|
||||||
|
} else
|
||||||
|
aclstr << _printDstService( compiler->getFirstSrv(rule) );
|
||||||
|
|
||||||
|
aclstr << _printLog( rule );
|
||||||
|
|
||||||
|
// aclstr << endl;
|
||||||
|
|
||||||
|
compiler->output << acl->addLine(aclstr.str());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2002 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: globalNATPool.cpp,v 1.1 2008/03/06 06:49:02 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 "NATCompiler_pix.h"
|
||||||
|
#include "helpers.h"
|
||||||
|
|
||||||
|
#include "fwbuilder/AddressRange.h"
|
||||||
|
#include "fwbuilder/Interface.h"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace libfwbuilder;
|
||||||
|
using namespace fwcompiler;
|
||||||
|
|
||||||
|
globalNATPool::globalNATPool(int id,Interface *ifs,Address *a)
|
||||||
|
{
|
||||||
|
nat_id=id;
|
||||||
|
iface=ifs;
|
||||||
|
addr= a;
|
||||||
|
if (Interface::cast(a)!=NULL || iface->isDyn()) {
|
||||||
|
type=INTERFACE;
|
||||||
|
} else {
|
||||||
|
type= (AddressRange::cast(a)!=NULL)?ADDRESS_RANGE:SINGLE_ADDRESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* global pool prints itself only once
|
||||||
|
*/
|
||||||
|
ostream& fwcompiler::operator<<(ostream &s,const globalNATPool &pool)
|
||||||
|
{
|
||||||
|
s << "global (" << pool.iface->getLabel() << ") " << pool.pool_no;
|
||||||
|
|
||||||
|
switch (pool.type) {
|
||||||
|
case globalNATPool::INTERFACE:
|
||||||
|
s << " interface" << endl;
|
||||||
|
break;
|
||||||
|
case globalNATPool::SINGLE_ADDRESS:
|
||||||
|
s << " " << pool.addr->getAddress().toString() << endl;
|
||||||
|
break;
|
||||||
|
case globalNATPool::ADDRESS_RANGE:
|
||||||
|
AddressRange *ar=AddressRange::cast(pool.addr);
|
||||||
|
s << " "
|
||||||
|
<< ar->getRangeStart().toString()
|
||||||
|
<< "-"
|
||||||
|
<< ar->getRangeEnd().toString()
|
||||||
|
<< " netmask "
|
||||||
|
<< pool.iface->getNetmask().toString()
|
||||||
|
<< endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
+643
@@ -0,0 +1,643 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Firewall Builder
|
||||||
|
|
||||||
|
Copyright (C) 2002 NetCitadel, LLC
|
||||||
|
|
||||||
|
Author: Vadim Kurland vadim@vk.crocodile.org
|
||||||
|
|
||||||
|
$Id: pix.cpp,v 1.2 2008/03/09 05:13:55 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 "config.h"
|
||||||
|
|
||||||
|
#include <qsettings.h>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <map>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# include <direct.h>
|
||||||
|
#else
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "PolicyCompiler_pix.h"
|
||||||
|
#include "NATCompiler_pix.h"
|
||||||
|
#include "OSConfigurator_pix_os.h"
|
||||||
|
|
||||||
|
#include "fwcompiler/Preprocessor.h"
|
||||||
|
|
||||||
|
#include "fwbuilder/Resources.h"
|
||||||
|
#include "fwbuilder/FWObjectDatabase.h"
|
||||||
|
#include "fwbuilder/Firewall.h"
|
||||||
|
#include "fwbuilder/Interface.h"
|
||||||
|
#include "fwbuilder/IPv4.h"
|
||||||
|
#include "fwbuilder/XMLTools.h"
|
||||||
|
#include "fwbuilder/FWException.h"
|
||||||
|
#include "fwbuilder/Tools.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_GETOPT_H
|
||||||
|
#include <getopt.h>
|
||||||
|
#else
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <getopt.h>
|
||||||
|
#else
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../common/init.cpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace libfwbuilder;
|
||||||
|
using namespace fwcompiler;
|
||||||
|
|
||||||
|
|
||||||
|
static const char *filename = NULL;
|
||||||
|
static const char *wdir = NULL;
|
||||||
|
static const char *fwobjectname = NULL;
|
||||||
|
static string ofname = "";
|
||||||
|
static int dl = 0;
|
||||||
|
static int drp = -1;
|
||||||
|
static int drn = -1;
|
||||||
|
static int verbose = 0;
|
||||||
|
static int test_mode = 0;
|
||||||
|
static int only_print_inspection_code = 0;
|
||||||
|
|
||||||
|
FWObjectDatabase *objdb = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
class UpgradePredicate: public XMLTools::UpgradePredicate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual bool operator()(const string &msg) const
|
||||||
|
{
|
||||||
|
msg.size(); // to make compiler happy about unused parameter
|
||||||
|
cout << "Data file has been created in the old version of Firewall Builder.\nLoad it in the GUI to convert it to the new version." << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class sort_by_net_zone {
|
||||||
|
public:
|
||||||
|
// explicit sort_by_net_zone();
|
||||||
|
bool operator()(const FWObject *a, const FWObject *b) {
|
||||||
|
if (Interface::constcast(a) && Interface::constcast(b)) {
|
||||||
|
string netzone_a=a->getStr("network_zone");
|
||||||
|
string netzone_b=b->getStr("network_zone");
|
||||||
|
if ( netzone_a==FWObjectDatabase::getAnyNetworkId()) return false;
|
||||||
|
if ( netzone_b==FWObjectDatabase::getAnyNetworkId()) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void usage(const char *name)
|
||||||
|
{
|
||||||
|
cout << "Firewall Builder: policy compiler for Cisco PIX firewall (with support for FWSM)" << endl;
|
||||||
|
cout << "Copyright 2002-2004 NetCitadel, LLC" << endl;
|
||||||
|
cout << "Version " << VERSION << "-" << RELEASE_NUM << endl;
|
||||||
|
cout << "Usage: " << name << " [-tvV] [-f filename.xml] [-d destdir] [-o output.fw] firewall_object_name" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char * const * argv)
|
||||||
|
{
|
||||||
|
if (argc<=1)
|
||||||
|
{
|
||||||
|
usage(argv0.c_str());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int opt;
|
||||||
|
|
||||||
|
while( (opt=getopt(argc,argv,"x:vVf:d:r:tLo:i")) != EOF )
|
||||||
|
{
|
||||||
|
switch(opt)
|
||||||
|
{
|
||||||
|
case 'i':
|
||||||
|
only_print_inspection_code++;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
wdir = strdup(optarg);
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
respath = string(optarg);
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
filename = strdup(optarg);
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
ofname = string(optarg);
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
if (*optarg=='p') {
|
||||||
|
++optarg;
|
||||||
|
drp = atoi(optarg);
|
||||||
|
} else {
|
||||||
|
if (*optarg=='n') {
|
||||||
|
++optarg;
|
||||||
|
drn = atoi(optarg);
|
||||||
|
} else {
|
||||||
|
if (isdigit(*optarg)) dl=atoi(optarg); // increase debug level
|
||||||
|
else {
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
test_mode++;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
verbose++;
|
||||||
|
break;
|
||||||
|
case 'V':
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(1);
|
||||||
|
case 'h':
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* can use init and init2 only after command line option "-r" has been read */
|
||||||
|
|
||||||
|
init(argv);
|
||||||
|
|
||||||
|
if((argc-1) != optind)
|
||||||
|
{
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fwobjectname = strdup( argv[optind++] );
|
||||||
|
|
||||||
|
if (ofname.empty())
|
||||||
|
{
|
||||||
|
ofname=string(fwobjectname)+".fw";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filename==NULL || fwobjectname==NULL)
|
||||||
|
{
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wdir==0) wdir="./";
|
||||||
|
|
||||||
|
if (
|
||||||
|
#ifdef _WIN32
|
||||||
|
_chdir(wdir)
|
||||||
|
#else
|
||||||
|
chdir(wdir)
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
|
cerr << "Can't change working directory to: " << wdir << endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (test_mode)
|
||||||
|
cout << "*** Running in test mode, all errors are ignored" << endl << endl;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
new Resources(respath+FS_SEPARATOR+"resources.xml");
|
||||||
|
|
||||||
|
/* create database */
|
||||||
|
objdb = new FWObjectDatabase();
|
||||||
|
|
||||||
|
/* load the data file */
|
||||||
|
UpgradePredicate upgrade_predicate;
|
||||||
|
|
||||||
|
if (verbose) cout << " *** Loading data ...";
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
objdb->setReadOnly( false );
|
||||||
|
objdb->load( sysfname, &upgrade_predicate, librespath);
|
||||||
|
objdb->setFileName("");
|
||||||
|
FWObjectDatabase *ndb = new FWObjectDatabase();
|
||||||
|
ndb->load(filename, &upgrade_predicate, librespath);
|
||||||
|
objdb->merge(ndb, NULL);
|
||||||
|
delete ndb;
|
||||||
|
objdb->setFileName(filename);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
objdb->setReadOnly( false );
|
||||||
|
objdb->load( filename, &upgrade_predicate, librespath);
|
||||||
|
objdb->setFileName(filename);
|
||||||
|
objdb->reIndex();
|
||||||
|
|
||||||
|
if (verbose) cout << " done\n";
|
||||||
|
|
||||||
|
/* why do I do this ?
|
||||||
|
|
||||||
|
FWObject *slib = objdb->findInIndex("syslib000");
|
||||||
|
if ( slib->isReadOnly()) slib->setReadOnly(false);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* some general sanity checks first
|
||||||
|
*/
|
||||||
|
Firewall* fw=objdb->findFirewallByName(fwobjectname);
|
||||||
|
FWOptions* options=fw->getOptionsObject();
|
||||||
|
|
||||||
|
bool pix_acl_basic=options->getBool("pix_acl_basic");
|
||||||
|
bool pix_acl_no_clear=options->getBool("pix_acl_no_clear");
|
||||||
|
bool pix_acl_substitution=options->getBool("pix_acl_substitution");
|
||||||
|
bool pix_add_clear_statements=options->getBool("pix_add_clear_statements");
|
||||||
|
|
||||||
|
if ( !pix_acl_basic &&
|
||||||
|
!pix_acl_no_clear &&
|
||||||
|
!pix_acl_substitution )
|
||||||
|
{
|
||||||
|
if ( pix_add_clear_statements ) options->setBool("pix_acl_basic",true);
|
||||||
|
else options->setBool("pix_acl_no_clear",true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (only_print_inspection_code)
|
||||||
|
{
|
||||||
|
OSConfigurator_pix_os *oscnf=NULL;
|
||||||
|
oscnf=new OSConfigurator_pix_os(objdb , fwobjectname);
|
||||||
|
oscnf->prolog();
|
||||||
|
|
||||||
|
cout << oscnf->getProtocolInspectionCommands();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Helper helper(NULL);
|
||||||
|
|
||||||
|
multimap<string, FWObject*> netzone_objects;
|
||||||
|
|
||||||
|
std::list<FWObject*> l2=fw->getByType(Interface::TYPENAME);
|
||||||
|
for (std::list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i)
|
||||||
|
{
|
||||||
|
Interface *iface=dynamic_cast<Interface*>(*i);
|
||||||
|
assert(iface);
|
||||||
|
/*
|
||||||
|
* missing labels on interfaces
|
||||||
|
*/
|
||||||
|
if (iface->getLabel()=="")
|
||||||
|
{
|
||||||
|
string lbl;
|
||||||
|
if (iface->getSecurityLevel()==0) lbl="outside";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (iface->getSecurityLevel()==100) lbl="inside";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char s[64];
|
||||||
|
sprintf(s,"dmz%d",iface->getSecurityLevel());
|
||||||
|
lbl=s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iface->setLabel(lbl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( iface->isDyn())
|
||||||
|
{
|
||||||
|
list<FWObject*> l3=iface->getByType(IPv4::TYPENAME);
|
||||||
|
if (l3.size()>0)
|
||||||
|
{
|
||||||
|
char errstr[256];
|
||||||
|
for (list<FWObject*>::iterator j=l3.begin(); j!=l3.end(); ++j)
|
||||||
|
if ( objdb->findAllReferences(*j).size()!=0 )
|
||||||
|
{
|
||||||
|
sprintf(errstr,
|
||||||
|
_("Dynamic interface %s has an IP address that is used in the firewall policy rule.\n"),
|
||||||
|
iface->getName().c_str() );
|
||||||
|
throw FWException(errstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(errstr,
|
||||||
|
_("Dynamic interface %s should not have an IP address object attached to it. This IP address object will be ignored.\n"),
|
||||||
|
iface->getName().c_str() );
|
||||||
|
cerr << errstr;
|
||||||
|
for (list<FWObject*>::iterator j=l3.begin(); j!=l3.end(); ++j)
|
||||||
|
iface->remove(*j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* no address
|
||||||
|
*/
|
||||||
|
if (iface->isRegular())
|
||||||
|
{
|
||||||
|
FWObject *ipv4=iface->getFirstByType(IPv4::TYPENAME);
|
||||||
|
if (ipv4==NULL)
|
||||||
|
throw FWException(
|
||||||
|
"Interface "+
|
||||||
|
iface->getName()+" ("+iface->getLabel()+") has no address." );
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* there shouldn't be two interfaces with the same security level
|
||||||
|
*/
|
||||||
|
for (std::list<FWObject*>::iterator j=l2.begin(); j!=l2.end(); ++j)
|
||||||
|
{
|
||||||
|
Interface *iface2=dynamic_cast<Interface*>(*j);
|
||||||
|
assert(iface2);
|
||||||
|
if (iface->getId()==iface2->getId()) continue;
|
||||||
|
|
||||||
|
if (iface->getSecurityLevel()==iface2->getSecurityLevel())
|
||||||
|
throw FWException(
|
||||||
|
"Security level of each interface should be unique, however interfaces "+
|
||||||
|
iface->getName()+" ("+iface->getLabel()+")"+
|
||||||
|
" and "+
|
||||||
|
iface2->getName()+" ("+iface2->getLabel()+")"+
|
||||||
|
" have the same security level."
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* in PIX, we need network zones to be defined for all interfaces
|
||||||
|
*/
|
||||||
|
string netzone_id=iface->getStr("network_zone");
|
||||||
|
if (netzone_id=="") {
|
||||||
|
throw FWException(
|
||||||
|
"Network zone definition is missing for interface "
|
||||||
|
+iface->getName()+" ("+iface->getLabel()+")");
|
||||||
|
}
|
||||||
|
FWObject *netzone=objdb->findInIndex(netzone_id);
|
||||||
|
if (netzone==NULL)
|
||||||
|
{
|
||||||
|
throw FWException(
|
||||||
|
"Network zone points at nonexisting object for interface "
|
||||||
|
+iface->getName()+" ("+iface->getLabel()+")");
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* netzone may be a group, in which case we need to expand it
|
||||||
|
* (recursively).
|
||||||
|
*
|
||||||
|
* 1. We create new temporary object (type Group).
|
||||||
|
*
|
||||||
|
* 2. put it in the database somewhere
|
||||||
|
*
|
||||||
|
* 3. add all objects that belong to the network zone to this
|
||||||
|
* group. We add objects directly, not as a reference.
|
||||||
|
*
|
||||||
|
* 4. finally replace reference to the old network zone object in the
|
||||||
|
* interface with reference to this new group.
|
||||||
|
*
|
||||||
|
* 5. we store ID of the original network zone object
|
||||||
|
* using iface->setStr("orig_netzone_id")
|
||||||
|
*
|
||||||
|
* This ensures netzones do not contain other groups and do not
|
||||||
|
* require any recursive expanding anymore. Since objects were added
|
||||||
|
* to netzones directly, we do not need to bother with dereferencing,
|
||||||
|
* too.
|
||||||
|
*/
|
||||||
|
list<FWObject*> ol;
|
||||||
|
helper.expand_group_recursive_no_cache(netzone,ol);
|
||||||
|
|
||||||
|
FWObject *nz=objdb->create(ObjectGroup::TYPENAME);
|
||||||
|
assert(nz!=NULL);
|
||||||
|
nz->setName("netzone_"+iface->getLabel());
|
||||||
|
objdb->add(nz);
|
||||||
|
|
||||||
|
for (list<FWObject*>::iterator j=ol.begin(); j!=ol.end(); ++j)
|
||||||
|
{
|
||||||
|
netzone_objects.insert( pair<string,FWObject*>(iface->getLabel(),*j));
|
||||||
|
nz->add(*j);
|
||||||
|
}
|
||||||
|
iface->setStr("orig_netzone_id", netzone_id );
|
||||||
|
iface->setStr("network_zone", nz->getId() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* the same object (network or host) can not belong to network zones
|
||||||
|
* of two different interfaces. Map netzone_objects holds pairs
|
||||||
|
* interface_id/object. We just make sure the same object does not
|
||||||
|
* appear in two pairs with different interfaces.
|
||||||
|
*/
|
||||||
|
multimap<string,FWObject*>::iterator k;
|
||||||
|
for (k=netzone_objects.begin(); k!=netzone_objects.end(); ++k)
|
||||||
|
{
|
||||||
|
multimap<string,FWObject*>::iterator l;
|
||||||
|
l=k;
|
||||||
|
++l;
|
||||||
|
for ( ; l!=netzone_objects.end(); ++l)
|
||||||
|
{
|
||||||
|
if ( l->second->getId() == k->second->getId() )
|
||||||
|
{
|
||||||
|
if (k->first==l->first)
|
||||||
|
throw FWException(
|
||||||
|
"Object "+l->second->getName()
|
||||||
|
+" is used more than once in network zone of interface '"
|
||||||
|
+k->first+"'");
|
||||||
|
else
|
||||||
|
throw FWException(
|
||||||
|
"Object "+l->second->getName()
|
||||||
|
+" is used more than once in network zones of the following interfaces: '"
|
||||||
|
+k->first+"' and '"+l->first+"'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* now sort interfaces by their network zone "width" (that is, more narrow
|
||||||
|
* network zone should go first, interface with network zone "any" should be
|
||||||
|
* the last)
|
||||||
|
*
|
||||||
|
std::sort(fw->begin(), fw->end(), sort_by_net_zone() );
|
||||||
|
*/
|
||||||
|
|
||||||
|
char timestr[256];
|
||||||
|
time_t tm;
|
||||||
|
|
||||||
|
tm=time(NULL);
|
||||||
|
strcpy(timestr,ctime(&tm));
|
||||||
|
timestr[ strlen(timestr)-1 ]='\0';
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
char* user_name=getenv("USERNAME");
|
||||||
|
#else
|
||||||
|
char* user_name=getenv("USER");
|
||||||
|
#endif
|
||||||
|
if (user_name==NULL)
|
||||||
|
throw FWException("Can't figure out your user name, aborting");
|
||||||
|
|
||||||
|
Preprocessor* prep=new Preprocessor(objdb , fwobjectname);
|
||||||
|
prep->compile();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process firewall options, build OS network configuration script
|
||||||
|
*/
|
||||||
|
OSConfigurator *oscnf=NULL;
|
||||||
|
oscnf=new OSConfigurator_pix_os(objdb , fwobjectname);
|
||||||
|
|
||||||
|
oscnf->prolog();
|
||||||
|
oscnf->processFirewallOptions();
|
||||||
|
|
||||||
|
|
||||||
|
/* create compilers and run the whole thing */
|
||||||
|
|
||||||
|
NATCompiler_pix *n=new NATCompiler_pix( objdb ,
|
||||||
|
fwobjectname, oscnf );
|
||||||
|
|
||||||
|
if (test_mode) n->setTestMode();
|
||||||
|
n->setDebugLevel( dl );
|
||||||
|
n->setDebugRule( drn );
|
||||||
|
n->setVerbose( verbose );
|
||||||
|
|
||||||
|
if ( n->prolog() > 0 ) {
|
||||||
|
n->compile();
|
||||||
|
n->epilog();
|
||||||
|
} else
|
||||||
|
cout << " Nothing to compile in NAT \n" << flush;
|
||||||
|
|
||||||
|
|
||||||
|
PolicyCompiler_pix *c=new PolicyCompiler_pix( objdb ,
|
||||||
|
fwobjectname ,
|
||||||
|
oscnf , n);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
ofstream ofile(ofname.c_str(), ios::out|ios::binary);
|
||||||
|
#else
|
||||||
|
ofstream ofile(ofname.c_str());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ofile << "!\n\
|
||||||
|
! This is automatically generated file. DO NOT MODIFY !\n\
|
||||||
|
!\n\
|
||||||
|
! Firewall Builder fwb_pix v" << VERSION << "-" << RELEASE_NUM << " \n\
|
||||||
|
!\n\
|
||||||
|
! Generated " << timestr
|
||||||
|
<< " "
|
||||||
|
<< tzname[0]
|
||||||
|
<< " by "
|
||||||
|
<< user_name;
|
||||||
|
|
||||||
|
ofile << endl;
|
||||||
|
|
||||||
|
string vers = fw->getStr("version");
|
||||||
|
string platform = fw->getStr("platform");
|
||||||
|
|
||||||
|
bool outbound_acl_supported = Resources::platform_res[platform]->getResourceBool(
|
||||||
|
string("/FWBuilderResources/Target/options/")+
|
||||||
|
"version_"+vers+
|
||||||
|
"/pix_outbound_acl_supported");
|
||||||
|
bool afpa = options->getBool("pix_assume_fw_part_of_any");
|
||||||
|
bool emulate_outb_acls = options->getBool("pix_emulate_out_acl");
|
||||||
|
bool generate_outb_acls = options->getBool("pix_generate_out_acl");
|
||||||
|
|
||||||
|
ofile << "!" << endl;
|
||||||
|
ofile << "!"
|
||||||
|
<< " Compiled for " << platform << " " << vers << endl;
|
||||||
|
ofile << "!"
|
||||||
|
<< " Outbound ACLs " << string((outbound_acl_supported)?"supported":"not supported")
|
||||||
|
<< endl;
|
||||||
|
if (!outbound_acl_supported)
|
||||||
|
{
|
||||||
|
ofile << "!"
|
||||||
|
<< " Emulate outbound ACLs: " << string((emulate_outb_acls)?"yes":"no")
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
ofile << "!"
|
||||||
|
<< " Generating outbound ACLs: " << string((generate_outb_acls)?"yes":"no")
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
ofile << "!"
|
||||||
|
<< " Assume firewall is part of 'any': " << string((afpa)?"yes":"no")
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
ofile << "!" << endl;
|
||||||
|
ofile << "!" << MANIFEST_MARKER << "* " << ofname << endl;
|
||||||
|
ofile << "!" << endl;
|
||||||
|
|
||||||
|
ofile << endl;
|
||||||
|
ofile << "!" << endl;
|
||||||
|
ofile << "! Prolog script:" << endl;
|
||||||
|
ofile << "!" << endl;
|
||||||
|
|
||||||
|
string pre_hook= fw->getOptionsObject()->getStr("pix_prolog_script");
|
||||||
|
ofile << pre_hook << endl;
|
||||||
|
|
||||||
|
ofile << "!" << endl;
|
||||||
|
ofile << "! End of prolog script:" << endl;
|
||||||
|
ofile << "!" << endl;
|
||||||
|
|
||||||
|
|
||||||
|
ofile << oscnf->getCompiledScript();
|
||||||
|
ofile << endl;
|
||||||
|
ofile << c->getCompiledScript();
|
||||||
|
ofile << endl;
|
||||||
|
ofile << n->getCompiledScript();
|
||||||
|
|
||||||
|
ofile << endl;
|
||||||
|
ofile << "!" << endl;
|
||||||
|
ofile << "! Epilog script:" << endl;
|
||||||
|
ofile << "!" << endl;
|
||||||
|
|
||||||
|
string post_hook= fw->getOptionsObject()->getStr("pix_epilog_script");
|
||||||
|
ofile << post_hook << endl;
|
||||||
|
|
||||||
|
ofile << endl;
|
||||||
|
ofile << "! End of epilog script:" << endl;
|
||||||
|
ofile << "!" << endl;
|
||||||
|
|
||||||
|
ofile.close();
|
||||||
|
|
||||||
|
cout << _(" Compiled successfully") << endl << flush;
|
||||||
|
|
||||||
|
} catch(libfwbuilder::FWException &ex) {
|
||||||
|
cerr << ex.toString() << endl;
|
||||||
|
return 1;
|
||||||
|
} catch (std::string s) {
|
||||||
|
cerr << s << endl;
|
||||||
|
return 1;
|
||||||
|
// } catch (std::exception ex) {
|
||||||
|
// cerr << "exception: " << ex.what() << endl;
|
||||||
|
// return 1;
|
||||||
|
// } catch (...) {
|
||||||
|
// cerr << "Unsupported exception";
|
||||||
|
// return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#-*- mode: makefile; tab-width: 4; -*-
|
||||||
|
#
|
||||||
|
include(../../qmake.inc)
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# PACKAGE = fwbuilder-pix-$$FWB_VERSION
|
||||||
|
#
|
||||||
|
# QMAKE_CXXFLAGS_DEBUG += -DPACKAGE="\"$$PACKAGE\""
|
||||||
|
# QMAKE_CXXFLAGS_RELEASE += -DPACKAGE="\"$$PACKAGE\""
|
||||||
|
|
||||||
|
SOURCES = NATCompiler_pix.cpp \
|
||||||
|
NATCompiler_pix_writers.cpp \
|
||||||
|
OSConfigurator_pix_os.cpp \
|
||||||
|
OSConfigurator_pix_os_fixups.cpp \
|
||||||
|
pix.cpp \
|
||||||
|
PIXObjectGroup.cpp \
|
||||||
|
PolicyCompiler_pix.cpp \
|
||||||
|
PolicyCompiler_pix_writers.cpp \
|
||||||
|
PolicyCompiler_pix_v6_acls.cpp
|
||||||
|
|
||||||
|
HEADERS = ../../config.h \
|
||||||
|
NATCompiler_pix.h \
|
||||||
|
OSConfigurator_pix_os.h \
|
||||||
|
PIXObjectGroup.h \
|
||||||
|
PolicyCompiler_pix.h \
|
||||||
|
../cisco_lib/PolicyCompiler_cisco.h \
|
||||||
|
../cisco_lib/ACL.h \
|
||||||
|
../cisco_lib/Helper.h
|
||||||
|
|
||||||
|
# CONFIG -= qt
|
||||||
|
QMAKE_COPY = /usr/bin/install -m 0755 -s
|
||||||
|
|
||||||
|
win32:CONFIG += console
|
||||||
|
|
||||||
|
INCLUDEPATH += ../cisco_lib/
|
||||||
|
|
||||||
|
win32:LIBS += $$PREFIX/fwbcisco.lib
|
||||||
|
!win32:LIBS += ../cisco_lib/libfwbcisco.a
|
||||||
|
|
||||||
|
LIBS += $$LIBS_FWCOMPILER
|
||||||
|
|
||||||
|
TARGET = fwb_pix
|
||||||
|
|
||||||
+1
-1
@@ -18,5 +18,5 @@ contains( HAVE_ANTLR_RUNTIME, 1 ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBDIRS += gui ipt pflib pf ipf ipfw
|
SUBDIRS += gui ipt pflib pf ipf ipfw cisco_lib iosacl pix
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# this is a comment
|
||||||
|
#
|
||||||
|
; this should be a comment too
|
||||||
|
;
|
||||||
|
|
||||||
|
192.168.1.1
|
||||||
|
192.168.1.2/32
|
||||||
|
192.168.1.3/30
|
||||||
|
192.168.2.128/25
|
||||||
|
192.168.1.200/32 # comment again
|
||||||
|
192.168.1.201/32 # this should work, too
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
#
|
||||||
|
# use this table to test run-time AddressTable object
|
||||||
|
# (this is just a small collection of addresses that sent spam to me
|
||||||
|
# on Nov 20 2005)
|
||||||
|
#
|
||||||
|
151.8.224.178 # this is also a comment
|
||||||
|
168.156.76.20
|
||||||
|
193.207.126.36
|
||||||
|
195.136.186.35
|
||||||
|
196.15.136.15
|
||||||
|
201.10.180.138
|
||||||
|
201.17.93.16
|
||||||
|
201.36.156.121
|
||||||
|
202.103.25.253
|
||||||
|
202.96.112.93
|
||||||
|
203.162.3.209
|
||||||
|
203.209.124.144
|
||||||
|
210.106.193.237
|
||||||
|
210.222.114.102
|
||||||
|
211.144.143.143
|
||||||
|
211.172.218.237
|
||||||
|
211.250.16.132
|
||||||
|
212.100.212.100
|
||||||
|
212.21.241.31
|
||||||
|
218.104.138.146
|
||||||
|
218.18.72.252
|
||||||
|
218.39.114.122
|
||||||
|
218.55.115.43
|
||||||
|
219.132.104.160
|
||||||
|
220.71.17.86
|
||||||
|
220.81.50.105
|
||||||
|
220.91.99.46
|
||||||
|
221.14.249.242
|
||||||
|
221.166.177.135
|
||||||
|
221.198.33.38
|
||||||
|
221.202.160.233
|
||||||
|
221.205.54.125
|
||||||
|
221.217.44.248
|
||||||
|
222.100.212.223
|
||||||
|
222.121.118.144
|
||||||
|
222.174.113.2
|
||||||
|
58.231.13.78
|
||||||
|
58.33.181.83
|
||||||
|
58.53.82.190
|
||||||
|
61.150.47.112
|
||||||
|
61.184.14.102
|
||||||
|
64.106.85.186
|
||||||
|
70.228.60.100
|
||||||
|
80.243.72.149
|
||||||
|
80.249.77.34
|
||||||
|
80.51.236.6
|
||||||
|
81.196.74.125
|
||||||
|
81.2.36.254
|
||||||
|
82.117.221.205
|
||||||
|
82.143.196.17
|
||||||
|
82.77.37.174
|
||||||
|
84.90.8.198
|
||||||
Executable
+15
@@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
N=$1
|
||||||
|
|
||||||
|
if which opendiff > /dev/null; then
|
||||||
|
TOOL="opendiff"
|
||||||
|
elif which tkdiff > /dev/null; then
|
||||||
|
TOOL="tkdiff "
|
||||||
|
else
|
||||||
|
TOOL="diff -u -b -B"
|
||||||
|
fi
|
||||||
|
|
||||||
|
$TOOL firewall${N}.fw.orig firewall${N}.fw
|
||||||
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
Executable
+15
@@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
$XMLFILE=@ARGV[0];
|
||||||
|
|
||||||
|
$DIFFCMD="diff -U 0 -u -b -B -I \"! Generated\" ";
|
||||||
|
|
||||||
|
while (<>) {
|
||||||
|
$str=$_;
|
||||||
|
while ( $str=~ /<Firewall / ) {
|
||||||
|
$str=~ /<Firewall [^>]+name="([^"]*).*$"/;
|
||||||
|
$fw=$1;
|
||||||
|
printf "$DIFFCMD %s.fw.orig %s.fw\n",$fw,$fw;
|
||||||
|
$str=~ s/^.*<Firewall [^>]+name="$fw"[^>]+>//;
|
||||||
|
}
|
||||||
|
}
|
||||||
Executable
+8
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
for f in *.fw; do
|
||||||
|
j=${f}.orig
|
||||||
|
mv $f $j
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
Executable
+17
@@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
$XMLFILE=@ARGV[0];
|
||||||
|
|
||||||
|
|
||||||
|
while (<>) {
|
||||||
|
$str=$_;
|
||||||
|
while ( $str=~ /<Firewall / ) {
|
||||||
|
$str=~ /<Firewall [^>]+name="([^"]*).*$"/;
|
||||||
|
$fw=$1;
|
||||||
|
printf "echo ====================== $fw =========================================\n";
|
||||||
|
printf "fwb_iosacl -v -f $XMLFILE $fw\n";
|
||||||
|
$str=~ s/^.*<Firewall [^>]+name="$fw"[^>]+>//;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# this is a comment
|
||||||
|
#
|
||||||
|
; this should be a comment too
|
||||||
|
;
|
||||||
|
|
||||||
|
192.168.1.1
|
||||||
|
192.168.1.2/32
|
||||||
|
192.168.1.3/30
|
||||||
|
192.168.2.128/25
|
||||||
|
192.168.1.200/32 # comment again
|
||||||
|
192.168.1.201/32 # this should work, too
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
#
|
||||||
|
# use this table to test run-time AddressTable object
|
||||||
|
# (this is just a small collection of addresses that sent spam to me
|
||||||
|
# on Nov 20 2005)
|
||||||
|
#
|
||||||
|
151.8.224.178 # this is also a comment
|
||||||
|
168.156.76.20
|
||||||
|
193.207.126.36
|
||||||
|
195.136.186.35
|
||||||
|
196.15.136.15
|
||||||
|
201.10.180.138
|
||||||
|
201.17.93.16
|
||||||
|
201.36.156.121
|
||||||
|
202.103.25.253
|
||||||
|
202.96.112.93
|
||||||
|
203.162.3.209
|
||||||
|
203.209.124.144
|
||||||
|
210.106.193.237
|
||||||
|
210.222.114.102
|
||||||
|
211.144.143.143
|
||||||
|
211.172.218.237
|
||||||
|
211.250.16.132
|
||||||
|
212.100.212.100
|
||||||
|
212.21.241.31
|
||||||
|
218.104.138.146
|
||||||
|
218.18.72.252
|
||||||
|
218.39.114.122
|
||||||
|
218.55.115.43
|
||||||
|
219.132.104.160
|
||||||
|
220.71.17.86
|
||||||
|
220.81.50.105
|
||||||
|
220.91.99.46
|
||||||
|
221.14.249.242
|
||||||
|
221.166.177.135
|
||||||
|
221.198.33.38
|
||||||
|
221.202.160.233
|
||||||
|
221.205.54.125
|
||||||
|
221.217.44.248
|
||||||
|
222.100.212.223
|
||||||
|
222.121.118.144
|
||||||
|
222.174.113.2
|
||||||
|
58.231.13.78
|
||||||
|
58.33.181.83
|
||||||
|
58.53.82.190
|
||||||
|
61.150.47.112
|
||||||
|
61.184.14.102
|
||||||
|
64.106.85.186
|
||||||
|
70.228.60.100
|
||||||
|
80.243.72.149
|
||||||
|
80.249.77.34
|
||||||
|
80.51.236.6
|
||||||
|
81.196.74.125
|
||||||
|
81.2.36.254
|
||||||
|
82.117.221.205
|
||||||
|
82.143.196.17
|
||||||
|
82.77.37.174
|
||||||
|
84.90.8.198
|
||||||
Executable
+15
@@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
N=$1
|
||||||
|
|
||||||
|
if which opendiff > /dev/null; then
|
||||||
|
TOOL="opendiff"
|
||||||
|
elif which tkdiff > /dev/null; then
|
||||||
|
TOOL="tkdiff "
|
||||||
|
else
|
||||||
|
TOOL="diff -u -b -B"
|
||||||
|
fi
|
||||||
|
|
||||||
|
$TOOL firewall${N}.fw.orig firewall${N}.fw
|
||||||
|
|
||||||
|
|
||||||
+14347
File diff suppressed because it is too large
Load Diff
Executable
+15
@@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
$XMLFILE=@ARGV[0];
|
||||||
|
|
||||||
|
$DIFFCMD="diff -0 -u -b -B -I \"! Generated\" ";
|
||||||
|
|
||||||
|
while (<>) {
|
||||||
|
$str=$_;
|
||||||
|
while ( $str=~ /<Firewall / ) {
|
||||||
|
$str=~ /<Firewall [^>]+name="([^"]*).*$"/;
|
||||||
|
$fw=$1;
|
||||||
|
printf "$DIFFCMD %s.fw.orig %s.fw\n",$fw,$fw;
|
||||||
|
$str=~ s/^.*<Firewall [^>]+name="$fw"[^>]+>//;
|
||||||
|
}
|
||||||
|
}
|
||||||
Executable
+8
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
for f in *.fw; do
|
||||||
|
j=${f}.orig
|
||||||
|
mv $f $j
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
Executable
+17
@@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
$XMLFILE=@ARGV[0];
|
||||||
|
|
||||||
|
|
||||||
|
while (<>) {
|
||||||
|
$str=$_;
|
||||||
|
while ( $str=~ /<Firewall / ) {
|
||||||
|
$str=~ /<Firewall [^>]+name="([^"]*).*$"/;
|
||||||
|
$fw=$1;
|
||||||
|
printf "echo ====================== $fw =========================================\n";
|
||||||
|
printf "fwb_pix -v -f $XMLFILE $fw\n";
|
||||||
|
$str=~ s/^.*<Firewall [^>]+name="$fw"[^>]+>//;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user