mirror of
https://github.com/fwbuilder/fwbuilder
synced 2026-03-25 04:37:22 +01:00
merging cisco and pix modules
This commit is contained in:
parent
9c966dbc91
commit
3dc8099fc3
@ -25,6 +25,9 @@ for d in src/ \
|
||||
src/pf/ \
|
||||
src/ipf/ \
|
||||
src/ipfw/ \
|
||||
src/cisco_lib \
|
||||
src/iosacl \
|
||||
src/pix \
|
||||
src/parsers/
|
||||
do
|
||||
(cd $d; ${QMAKE} $C)
|
||||
|
||||
86
src/cisco_lib/ACL.cpp
Normal file
86
src/cisco_lib/ACL.cpp
Normal file
@ -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();
|
||||
}
|
||||
|
||||
99
src/cisco_lib/ACL.h
Normal file
99
src/cisco_lib/ACL.h
Normal file
@ -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
|
||||
255
src/cisco_lib/Helper.cpp
Normal file
255
src/cisco_lib/Helper.cpp
Normal file
@ -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();
|
||||
}
|
||||
109
src/cisco_lib/Helper.h
Normal file
109
src/cisco_lib/Helper.h
Normal file
@ -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
|
||||
882
src/cisco_lib/PolicyCompiler_cisco.cpp
Normal file
882
src/cisco_lib/PolicyCompiler_cisco.cpp
Normal file
@ -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()
|
||||
{
|
||||
}
|
||||
|
||||
460
src/cisco_lib/PolicyCompiler_cisco.h
Normal file
460
src/cisco_lib/PolicyCompiler_cisco.h
Normal file
@ -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
|
||||
320
src/cisco_lib/PolicyCompiler_cisco_acls.cpp
Normal file
320
src/cisco_lib/PolicyCompiler_cisco_acls.cpp
Normal file
@ -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;
|
||||
}
|
||||
|
||||
24
src/cisco_lib/cisco_lib.pro
Normal file
24
src/cisco_lib/cisco_lib.pro
Normal file
@ -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;
|
||||
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();
|
||||
|
||||
#if defined(Q_OS_WIN32) || defined(Q_OS_MACX)
|
||||
|
||||
230
src/iosacl/OSConfigurator_ios.cpp
Normal file
230
src/iosacl/OSConfigurator_ios.cpp
Normal file
@ -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) ;
|
||||
}
|
||||
|
||||
59
src/iosacl/OSConfigurator_ios.h
Normal file
59
src/iosacl/OSConfigurator_ios.h
Normal file
@ -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
|
||||
404
src/iosacl/PolicyCompiler_iosacl.cpp
Normal file
404
src/iosacl/PolicyCompiler_iosacl.cpp
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
267
src/iosacl/PolicyCompiler_iosacl.h
Normal file
267
src/iosacl/PolicyCompiler_iosacl.h
Normal file
@ -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
|
||||
434
src/iosacl/PolicyCompiler_iosacl_writers.cpp
Normal file
434
src/iosacl/PolicyCompiler_iosacl_writers.cpp
Normal file
@ -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;
|
||||
}
|
||||
|
||||
429
src/iosacl/iosacl.cpp
Normal file
429
src/iosacl/iosacl.cpp
Normal file
@ -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;
|
||||
}
|
||||
36
src/iosacl/iosacl.pro
Normal file
36
src/iosacl/iosacl.pro
Normal file
@ -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
|
||||
|
||||
1590
src/pix/NATCompiler_pix.cpp
Normal file
1590
src/pix/NATCompiler_pix.cpp
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
504
src/pix/NATCompiler_pix.h
Normal file
504
src/pix/NATCompiler_pix.h
Normal file
@ -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
|
||||
562
src/pix/NATCompiler_pix_writers.cpp
Normal file
562
src/pix/NATCompiler_pix_writers.cpp
Normal file
@ -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;
|
||||
}
|
||||
|
||||
|
||||
535
src/pix/OSConfigurator_pix_os.cpp
Normal file
535
src/pix/OSConfigurator_pix_os.cpp
Normal file
@ -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) ;
|
||||
}
|
||||
|
||||
77
src/pix/OSConfigurator_pix_os.h
Normal file
77
src/pix/OSConfigurator_pix_os.h
Normal file
@ -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
|
||||
447
src/pix/OSConfigurator_pix_os_fixups.cpp
Normal file
447
src/pix/OSConfigurator_pix_os_fixups.cpp
Normal file
@ -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();
|
||||
}
|
||||
118
src/pix/PIXObjectGroup.cpp
Normal file
118
src/pix/PIXObjectGroup.cpp
Normal file
@ -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
|
||||
94
src/pix/PIXObjectGroup.h
Normal file
94
src/pix/PIXObjectGroup.h
Normal file
@ -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
|
||||
845
src/pix/PolicyCompiler_pix.cpp
Normal file
845
src/pix/PolicyCompiler_pix.cpp
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
327
src/pix/PolicyCompiler_pix.h
Normal file
327
src/pix/PolicyCompiler_pix.h
Normal file
@ -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
|
||||
361
src/pix/PolicyCompiler_pix_v6_acls.cpp
Normal file
361
src/pix/PolicyCompiler_pix_v6_acls.cpp
Normal file
@ -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;
|
||||
}
|
||||
|
||||
|
||||
688
src/pix/PolicyCompiler_pix_writers.cpp
Normal file
688
src/pix/PolicyCompiler_pix_writers.cpp
Normal file
@ -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;
|
||||
}
|
||||
|
||||
75
src/pix/globalNATPool.cpp
Normal file
75
src/pix/globalNATPool.cpp
Normal file
@ -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
src/pix/pix.cpp
Normal file
643
src/pix/pix.cpp
Normal file
@ -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;
|
||||
}
|
||||
43
src/pix/pix.pro
Normal file
43
src/pix/pix.pro
Normal file
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
14
test/iosacl/addr-table-1.tbl
Normal file
14
test/iosacl/addr-table-1.tbl
Normal file
@ -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
|
||||
|
||||
|
||||
|
||||
57
test/iosacl/block-hosts.tbl
Normal file
57
test/iosacl/block-hosts.tbl
Normal file
@ -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
|
||||
15
test/iosacl/do-diff
Executable file
15
test/iosacl/do-diff
Executable file
@ -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
|
||||
|
||||
|
||||
2206
test/iosacl/objects.fwb
Normal file
2206
test/iosacl/objects.fwb
Normal file
File diff suppressed because it is too large
Load Diff
15
test/iosacl/quick-cmp.sh
Executable file
15
test/iosacl/quick-cmp.sh
Executable file
@ -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"[^>]+>//;
|
||||
}
|
||||
}
|
||||
8
test/iosacl/recycle
Executable file
8
test/iosacl/recycle
Executable file
@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
for f in *.fw; do
|
||||
j=${f}.orig
|
||||
mv $f $j
|
||||
done
|
||||
|
||||
|
||||
17
test/iosacl/run.all
Executable file
17
test/iosacl/run.all
Executable file
@ -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"[^>]+>//;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
14
test/pix/addr-table-1.tbl
Normal file
14
test/pix/addr-table-1.tbl
Normal file
@ -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
|
||||
|
||||
|
||||
|
||||
57
test/pix/block-hosts.tbl
Normal file
57
test/pix/block-hosts.tbl
Normal file
@ -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
|
||||
15
test/pix/do-diff
Executable file
15
test/pix/do-diff
Executable file
@ -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
test/pix/objects.fwb
Normal file
14347
test/pix/objects.fwb
Normal file
File diff suppressed because it is too large
Load Diff
15
test/pix/quick-cmp.sh
Executable file
15
test/pix/quick-cmp.sh
Executable file
@ -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"[^>]+>//;
|
||||
}
|
||||
}
|
||||
8
test/pix/recycle
Executable file
8
test/pix/recycle
Executable file
@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
for f in *.fw; do
|
||||
j=${f}.orig
|
||||
mv $f $j
|
||||
done
|
||||
|
||||
|
||||
17
test/pix/run.all
Executable file
17
test/pix/run.all
Executable file
@ -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"[^>]+>//;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user