1
0
mirror of https://github.com/fwbuilder/fwbuilder synced 2026-03-23 19:57:21 +01:00
fwbuilder/src/libgui/Importer.cpp
Vadim Kurland 85291843f5 * Importer.cpp (ignoreCurrentInterface): see #2152 "ASA Import -
shutdown interfaces". Importer recognizes and skips ASA interfaces
in "shutdown" mode.
2011-03-06 21:27:28 -08:00

1239 lines
36 KiB
C++

/*
Firewall Builder
Copyright (C) 2007 NetCitadel, LLC
Author: Vadim Kurland vadim@fwbuilder.org
$Id$
This program is free software which we release under the GNU General Public
License. You may redistribute and/or modify this program under the terms
of that license as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
To get a copy of the GNU General Public License, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../../config.h"
#include "global.h"
#include "utils_no_qt.h"
#include "platforms.h"
#include "Importer.h"
#include <string>
#include <ios>
#include <iostream>
#include <algorithm>
#include "fwbuilder/FWObject.h"
#include "fwbuilder/FWObjectDatabase.h"
#include "fwbuilder/Network.h"
#include "fwbuilder/Address.h"
#include "fwbuilder/DNSName.h"
#include "fwbuilder/AddressRange.h"
#include "fwbuilder/IPService.h"
#include "fwbuilder/ICMPService.h"
#include "fwbuilder/TCPService.h"
#include "fwbuilder/UDPService.h"
#include "fwbuilder/CustomService.h"
#include "fwbuilder/TagService.h"
#include "fwbuilder/Resources.h"
#include "fwbuilder/Policy.h"
#include "fwbuilder/NAT.h"
#include "fwbuilder/RuleElement.h"
#include "FWWindow.h"
#include "ProjectPanel.h"
#include "FWBTree.h"
#include <QString>
#include <QtDebug>
using namespace libfwbuilder;
using namespace std;
// a functor to join list<string> into a string with separator sep
class join : public std::unary_function<std::string, void>
{
std::string *result;
std::string separator;
public:
join(std::string *res, const std::string &s)
{ result = res; separator = s; }
void operator()(std::string &s);
};
void join::operator()(string &s)
{
if (!result->empty()) *result += separator;
*result += s;
}
FWObject* Importer::createObject(const std::string &objType,
const std::string &objName)
{
assert(library!=NULL);
FWBTree tree ;
FWObject *slot = tree.getStandardSlotForObject(library,objType.c_str());
return createObject(slot, objType, objName);
}
FWObject* Importer::createObject(FWObject *parent,
const std::string &objType,
const std::string &objName)
{
assert(library!=NULL);
FWObject* o = library->getRoot()->create(objType);
if (parent != NULL)
{
parent->add(o);
}
o->setName(objName);
return o;
}
std::string Importer::getBadRuleColor()
{
return "#C86E6E";
}
void Importer::SaveTmpAddrToSrc()
{
src_a = tmp_a;
src_nm = tmp_nm;
}
void Importer::SaveTmpAddrToDst()
{
dst_a = tmp_a;
dst_nm = tmp_nm;
}
void Importer::SaveTmpPortToSrc()
{
src_port_op = tmp_port_op;
src_port_spec = tmp_port_spec;
}
void Importer::SaveTmpPortToDst()
{
dst_port_op = tmp_port_op;
dst_port_spec = tmp_port_spec;
}
Importer::Importer(FWObject *_lib,
const std::string &_platform,
std::istringstream &_input,
Logger *log,
const std::string &fwname) : input(_input)
{
this->fwname = fwname;
library = _lib;
fw = NULL;
error_counter = 0;
logger = log;
platform = _platform;
clear();
current_interface = NULL;
current_ruleset = NULL;
current_rule = NULL;
custom_service_code_tracker = 0;
tcp_flag_names[libfwbuilder::TCPService::URG]="u";
tcp_flag_names[libfwbuilder::TCPService::ACK]="a";
tcp_flag_names[libfwbuilder::TCPService::PSH]="p";
tcp_flag_names[libfwbuilder::TCPService::RST]="r";
tcp_flag_names[libfwbuilder::TCPService::SYN]="s";
tcp_flag_names[libfwbuilder::TCPService::FIN]="f";
tcp_flag_names[98]="N"; // NONE
tcp_flag_names[99]="A"; // ALL
}
void Importer::run()
{
// create and run parsers in derived classes
}
Importer::~Importer()
{
all_rulesets.clear();
all_interfaces.clear();
}
void Importer::clear()
{
action = "";
protocol = "";
src_a = "";
src_nm = "";
src_port_op = "";
src_port_spec = "";
dst_a = "";
dst_nm = "";
dst_port_op = "";
dst_port_spec = "";
tmp_a = "";
tmp_nm = "";
tmp_port_op = "";
tmp_port_spec = "";
logging = false;
established = false;
fragments = false;
icmp_spec = "";
icmp_code = "";
icmp_type = "";
time_range_name = "";
if (!tcp_flags_mask.empty()) tcp_flags_mask.clear();
if (!tcp_flags_comp.empty()) tcp_flags_comp.clear();
if (!tmp_tcp_flags_list.empty()) tmp_tcp_flags_list.clear();
}
Firewall* Importer::getFirewallObject()
{
if (fw!=NULL) return fw;
FWObject *nobj = createObject(Firewall::TYPENAME, fwname);
fw = Firewall::cast(nobj);
fw->setStr("platform", platform);
Resources::setDefaultTargetOptions(platform , fw);
// std::map<std::string,std::string> platforms = Resources::getPlatforms();
// std::map<std::string,std::string>::iterator i;
// for (i=platforms.begin(); i!=platforms.end(); i++)
// Resources::setDefaultTargetOptions( i->first , fw );
// std::map<std::string,std::string> OSs = Resources::getOS();
// for (i=OSs.begin(); i!=OSs.end(); i++)
// Resources::setDefaultTargetOptions( i->first , fw );
return fw;
}
/*
* Creates firewall object and sets its name
*
* This assumes that configuration clase that declares host name
* comes first (true for Ciscos, but may not be true for others)
*
*/
void Importer::setHostName(const std::string &hn)
{
getFirewallObject()->setName(hn);
*logger << "Host name: " + hn + "\n";
}
void Importer::setDiscoveredVersion(const std::string &v)
{
discovered_version = v;
*logger << "Version: " + v + "\n";
}
void Importer::newInterface(const std::string &name)
{
if (all_interfaces.count(name)>0) return;
FWObject *nobj = createObject(getFirewallObject(), Interface::TYPENAME, name);
current_interface = Interface::cast(nobj);
current_interface->setUnnumbered(true);
all_interfaces[name] = current_interface;
*logger << "New interface: " + name + "\n";
}
/*
* We call this when importer for PIX or IOS encounters interface in
* state "shutdown"
*/
void Importer::ignoreCurrentInterface()
{
if (current_interface)
{
string name = current_interface->getName();
current_interface->getParent()->remove(current_interface);
all_interfaces.erase(name);
}
}
void Importer::addAddressObjectToInterface(Interface*intf,
const string &addr,
const string &netm)
{
intf->setUnnumbered(false);
if (addr == "dhcp") intf->setDyn(true);
else
{
string aname = getFirewallObject()->getName() + ":" + intf->getName() + ":ip";
FWObject *nobj = createObject(intf, IPv4::TYPENAME, aname);
IPv4::cast(nobj)->setAddress( InetAddr(addr) );
IPv4::cast(nobj)->setNetmask( InetAddr(netm) );
}
}
void Importer::addInterfaceAddress(const std::string &a,
const std::string &nm)
{
if (current_interface!=NULL)
{
addAddressObjectToInterface(current_interface, a, nm);
*logger << "Interface address: " + a + "/" + nm + "\n";
}
}
void Importer::addInterfaceAddress(const std::string &label,
const std::string &a,
const std::string &nm)
{
map<const string,Interface*>::iterator it;
for (it=all_interfaces.begin(); it!=all_interfaces.end(); ++it)
{
Interface *intf = it->second;
if (intf->getLabel() == label)
{
addAddressObjectToInterface(intf, a, nm);
*logger << "Interface address: " + a + "/" + nm + "\n";
}
}
}
void Importer::setInterfaceComment(const std::string &descr)
{
// current_interface can be NULL if parser encountered command
// that looked like interface description but in reality was
// description of something else. For example this happens when
// it finds command "description" under "controller" in Cisco router
// configuration.
if (current_interface!=NULL)
{
current_interface->setComment(descr);
*logger << "Interface comment: " + descr + "\n";
}
}
void Importer::setInterfaceLabel(const std::string &descr)
{
if (current_interface!=NULL)
{
current_interface->setLabel(descr);
*logger << "Interface label: " + descr + "\n";
}
}
void Importer::setInterfaceParametes(const std::string &phys_intf_or_label,
const std::string &label,
const std::string &sec_level)
{
*logger << "Interface parameters: " + phys_intf_or_label + " " + label + " " + sec_level + "\n";
if (all_interfaces.count(phys_intf_or_label))
{
// since first arg. is physical interface name, this must be pix6
// "nameif ethernet0 outside security0"
Interface *intf = all_interfaces[phys_intf_or_label];
intf->setLabel(label);
QRegExp pix6_sec_level("security(\\d+)");
if (pix6_sec_level.indexIn(sec_level.c_str()) > -1)
intf->setSecurityLevel(pix6_sec_level.cap(1).toInt());
} else
{
// since first arg is not physical interface name, it must be a label
// as in pix7 config
//
// interface Ethernet0.101
// vlan 101
// nameif outside
// security-level 0
// ip address 192.0.2.253 255.255.255.0
setInterfaceLabel(phys_intf_or_label);
}
}
void Importer::setInterfaceSecurityLevel(const std::string &seclevel)
{
if (current_interface!=NULL)
{
QString sl(seclevel.c_str());
current_interface->setSecurityLevel(sl.toInt());
}
}
void Importer::setInterfaceVlanId(const std::string &vlan_id)
{
if (current_interface!=NULL)
{
FWOptions *ifopt = (Interface::cast(current_interface))->getOptionsObject();
ifopt->setStr("type", "8021q");
ifopt->setStr("vlan_id", vlan_id);
}
}
void Importer::addRuleComment(const std::string &comm)
{
rule_comment += comm;
*logger << "Rule comment: " + comm + "\n";
}
UnidirectionalRuleSet* Importer::checkUnidirRuleSet(
const std::string &ruleset_name)
{
return all_rulesets[ruleset_name];
}
UnidirectionalRuleSet* Importer::getUnidirRuleSet(const std::string &ruleset_name)
{
UnidirectionalRuleSet *rs = all_rulesets[ruleset_name];
if (rs==NULL)
{
// got 'ip access-group' command before the access list was defined
rs = new UnidirectionalRuleSet();
rs->name = ruleset_name;
FWObjectDatabase *dbroot = getFirewallObject()->getRoot();
if (ruleset_name == "nat")
rs->ruleset = RuleSet::cast(dbroot->create(NAT::TYPENAME));
else
rs->ruleset = RuleSet::cast(dbroot->create(Policy::TYPENAME));
rs->ruleset->setName(ruleset_name);
all_rulesets[ruleset_name] = rs;
// add this ruleset to the firewall temporarily
// because ruleset must belong to the tree somewhere in
// order for other objects to be added properly.
getFirewallObject()->add(rs->ruleset);
}
return rs;
}
/*
* associate ruleset <ruleset_name> with interface <intf_name>
* and direction <dir>
*
* if <intf_name> is empty, use current_interface
*
* Note that a ruleset may be associated with multiple interfaces
* and each association can have different direction.
*/
void Importer::setInterfaceAndDirectionForRuleSet(const std::string &ruleset_name,
const std::string &_intf_name,
const std::string &_dir)
{
UnidirectionalRuleSet *rs = getUnidirRuleSet(ruleset_name);
std::string intf;
if ( !_intf_name.empty()) intf = _intf_name;
else intf = current_interface->getName();
if (rs->intf_dir.count(intf)==0)
rs->intf_dir[intf] = _dir;
else
{
// already have this interface with some direction
// compare direction, if different, switcht to "both"
if (rs->intf_dir[intf] != "both" && rs->intf_dir[intf] != _dir)
rs->intf_dir[intf] = "both";
}
ostringstream str;
str << "Interface " << _intf_name
<< " ruleset " << ruleset_name
<< " direction '" << _dir << "' "
<< "(set to '" << rs->intf_dir[intf] << "')"
<< "\n";
*logger << str.str();
}
void Importer::newUnidirRuleSet(const std::string &ruleset_name)
{
current_ruleset = getUnidirRuleSet(ruleset_name); // creates if new
*logger << "Ruleset: " + ruleset_name + "\n";
}
/*
* Grammar must ensure the call to setDefaultAction() happens
* after the call to newUnidirRuleSet()
*
*/
void Importer::setDefaultAction(const std::string &iptables_action_name)
{
string default_action_str = "Deny";
if (iptables_action_name == "ACCEPT")
{
current_ruleset->default_action = PolicyRule::Accept;
default_action_str = "Accept";
} else current_ruleset->default_action = PolicyRule::Deny;
*logger << "Default action: " + default_action_str + "\n";
}
void Importer::newPolicyRule()
{
FWObjectDatabase *dbroot = getFirewallObject()->getRoot();
FWObject *nobj = dbroot->create(PolicyRule::TYPENAME);
current_rule = Rule::cast(nobj);
// check if all child objects were populated properly
FWOptions *ropt = current_rule->getOptionsObject();
assert(ropt!=NULL);
ropt->setBool("stateless",true);
}
void Importer::newNATRule()
{
FWObjectDatabase *dbroot = getFirewallObject()->getRoot();
FWObject *nobj = dbroot->create(NATRule::TYPENAME);
current_rule = Rule::cast(nobj);
}
void Importer::pushRule()
{
assert(current_ruleset!=NULL);
assert(current_rule!=NULL);
// populate all elements of the rule
PolicyRule *rule = PolicyRule::cast(current_rule);
if (action=="permit") rule->setAction(PolicyRule::Accept);
if (action=="deny") rule->setAction(PolicyRule::Deny);
addSrc();
addDst();
addSrv();
rule->setLogging(logging);
// then add it to the current ruleset
current_ruleset->ruleset->add(current_rule);
current_rule->setComment(rule_comment);
// *logger << "Rule: " << action << " "
// << protocol << " "
// << src_a << "/" << src_nm << " ";
// if (dst_a!="")
// *logger << dst_a << "/" << dst_nm << " ";
// *logger << "\n";
current_rule = NULL;
rule_comment = "";
clear();
}
FWObject* Importer::makeSrcObj()
{
if ( (src_a=="" && src_nm=="") ||
(src_a==InetAddr::getAny().toString() &&
src_nm==InetAddr::getAny().toString()))
return NULL; // this is 'any'
if (src_nm=="") src_nm=InetAddr::getAllOnes().toString();
return createAddress(src_a, src_nm);
}
FWObject* Importer::makeDstObj()
{
if ( (dst_a=="" && dst_nm=="") ||
(dst_a==InetAddr::getAny().toString() &&
dst_nm==InetAddr::getAny().toString()))
return NULL; // this is 'any'
if (dst_nm=="") dst_nm=InetAddr::getAllOnes().toString();
return createAddress(dst_a, dst_nm);
}
FWObject* Importer::makeSrvObj()
{
if (protocol=="") return NULL; // this is 'any'
FWObject *s;
if (protocol=="icmp") s = createICMPService();
else
if (protocol=="tcp") s = createTCPService();
else
if (protocol=="udp") s = createUDPService();
else
s = createIPService();
// if create*Service returns NULL, this is 'any'
return s;
}
void Importer::addSrc()
{
PolicyRule *rule = PolicyRule::cast(current_rule);
RuleElementSrc* src = rule->getSrc();
assert(src!=NULL);
FWObject *s = makeSrcObj();
if (s) src->addRef( s );
}
void Importer::addDst()
{
PolicyRule *rule = PolicyRule::cast(current_rule);
RuleElementDst* dst = rule->getDst();
assert(dst!=NULL);
FWObject *s = makeDstObj();
if (s) dst->addRef( s );
}
void Importer::addSrv()
{
PolicyRule *rule = PolicyRule::cast(current_rule);
RuleElementSrv* srv = rule->getSrv();
assert(srv!=NULL);
FWObject *s = makeSrvObj();
if (s) srv->addRef( s );
}
void Importer::addOSrc()
{
NATRule *rule = NATRule::cast(current_rule);
RuleElementOSrc* src = rule->getOSrc();
assert(src!=NULL);
FWObject *s = makeSrcObj();
if (s) src->addRef( s );
}
void Importer::addODst()
{
NATRule *rule = NATRule::cast(current_rule);
RuleElementODst* dst = rule->getODst();
assert(dst!=NULL);
FWObject *s = makeDstObj();
if (s) dst->addRef( s );
}
void Importer::addOSrv()
{
NATRule *rule = NATRule::cast(current_rule);
RuleElementOSrv* srv = rule->getOSrv();
assert(srv!=NULL);
FWObject *s= makeSrvObj();
if (s) srv->addRef( s );
}
Firewall* Importer::finalize()
{
return fw;
}
FWObject* Importer::getCustomService(const std::string &platform,
const std::string &code,
const std::string &protocol)
{
// this assumes protocol is represented by a number
if (custom_service_codes.count(platform + code)==0)
{
custom_service_codes[platform + code] = custom_service_code_tracker;
custom_service_code_tracker++;
}
std::ostringstream nstr, cstr, sstr;
nstr << "cust-" << custom_service_codes[platform + code];
if (!protocol.empty()) nstr << "-" << protocol;
sstr << "cust-" << custom_service_codes[platform + code] << "-" << protocol;
cstr << "Imported from " << getFirewallObject()->getName() << "\n"
<< "code: " << code;
if (!protocol.empty()) cstr << "\n" << "protocol: " << protocol;
if (all_objects.count(sstr.str())!=0) return all_objects[sstr.str()];
CustomService *s = CustomService::cast(
createObject(CustomService::TYPENAME, nstr.str()));
if (!protocol.empty()) s->setProtocol(protocol);
s->setCodeForPlatform(platform, code);
s->setComment(cstr.str());
all_objects[sstr.str()] = s;
ostringstream str;
str << "Custom Service object: " << nstr.str()
<< ": "
<< platform
<< ": "
<< code
<< "\n";
*logger << str.str();
return s;
}
FWObject* Importer::getIPService(int proto)
{
// this assumes protocol is represented by a number
std::ostringstream nstr, cstr, sstr;
nstr << "ip-" << proto;
sstr << "ip-" << proto;
if (fragments)
{
nstr << " fragm";
sstr << "-fragm";
}
cstr << "Imported from " << getFirewallObject()->getName() << "\n"
<< "protocol " << proto;
if (all_objects.count(sstr.str())!=0) return all_objects[sstr.str()];
if ( proto==0 && !fragments)
return NULL; // any
IPService *s = IPService::cast(createObject(IPService::TYPENAME, nstr.str()));
s->setInt("protocol_num", proto);
s->setBool("fragm", fragments);
s->setComment(cstr.str());
all_objects[sstr.str()] = s;
*logger << "IP Service object: " + nstr.str() + "\n";
return s;
}
FWObject* Importer::getICMPService(int type, int code)
{
std::ostringstream nstr;
nstr << "icmp " << type << "/" << code;
std::ostringstream cstr;
cstr << "Imported from " << getFirewallObject()->getName()
<< " type " << type << " code " << code;
std::ostringstream sstr;
sstr << "icmp-" << type << "/" << code;
if (all_objects.count(sstr.str())!=0) return all_objects[sstr.str()];
ICMPService *s = ICMPService::cast( createObject(ICMPService::TYPENAME,nstr.str()));
s->setInt("type", type);
s->setInt("code", code);
s->setComment(cstr.str());
all_objects[sstr.str()] = s;
*logger << "ICMP Service object: " + nstr.str() + "\n";
return s;
}
FWObject* Importer::getTCPService(int srs, int sre,
int drs, int dre,
bool established,
std::list<int> &flags_mask,
std::list<int> &flags_comp)
{
std::list<int>::iterator li;
std::ostringstream sstr;
sstr << "tcp-" << srs << "-" << sre << ":" << drs << "-" << dre;
if (established) sstr << "-est";
if (!flags_mask.empty() && !flags_comp.empty())
{
// TCP flags
for (li = flags_mask.begin(); li != flags_mask.end(); ++li)
sstr << "f" << *li;
for (li = flags_comp.begin(); li != flags_comp.end(); ++li)
sstr << "f" << *li;
}
if (all_objects.count(sstr.str())!=0) return all_objects[sstr.str()];
std::ostringstream cstr;
cstr << "Imported from " << getFirewallObject()->getName() << "\n"
<< srs << "-" << sre << ":" << drs << "-" << dre;
if (established) cstr << " est";
if (!flags_mask.empty() && !flags_comp.empty()) cstr << " flags";
std::ostringstream nstr;
nstr << "tcp " ;
if (srs!=0 || sre!=0) nstr << srs << "-" << sre << ":";
if (drs!=0 || dre!=0) nstr << drs << "-" << dre;
if (established) nstr << " est";
if (!flags_mask.empty() && !flags_comp.empty())
{
for (li = flags_mask.begin(); li != flags_mask.end(); ++li)
nstr << tcp_flag_names[*li];
nstr << "/";
for (li = flags_comp.begin(); li != flags_comp.end(); ++li)
nstr << tcp_flag_names[*li];
}
TCPService* s = TCPService::cast(
createObject(TCPService::TYPENAME, nstr.str()));
s->setSrcRangeStart(srs);
s->setSrcRangeEnd(sre);
s->setDstRangeStart(drs);
s->setDstRangeEnd(dre);
if (!flags_mask.empty() && !flags_comp.empty())
{
// TCP flags
for (li = flags_mask.begin(); li != flags_mask.end(); ++li)
{
switch (*li)
{
case 99: // ALL
s->setAllTCPFlagMasks();
break;
case 98: // NONE
s->clearAllTCPFlagMasks();
break;
default:
s->setTCPFlagMask( TCPService::TCPFlag(*li), true);
}
}
for (li = flags_comp.begin(); li != flags_comp.end(); ++li)
{
switch (*li)
{
case 99: // ALL
s->setTCPFlag( TCPService::URG, true);
s->setTCPFlag( TCPService::ACK, true);
s->setTCPFlag( TCPService::PSH, true);
s->setTCPFlag( TCPService::RST, true);
s->setTCPFlag( TCPService::SYN, true);
s->setTCPFlag( TCPService::FIN, true);
break;
case 98: // NONE
s->clearAllTCPFlags();
break;
default:
s->setTCPFlag( TCPService::TCPFlag(*li), true);
}
}
}
s->setEstablished(established);
s->setComment(cstr.str());
all_objects[sstr.str()] = s;
*logger << "TCP Service object: " + nstr.str() + "\n";
return s;
}
FWObject* Importer::getUDPService(int srs, int sre, int drs, int dre)
{
std::ostringstream sstr;
sstr << "udp-" << srs << "-" << sre << ":" << drs << "-" << dre;
if (all_objects.count(sstr.str())!=0) return all_objects[sstr.str()];
std::ostringstream cstr;
cstr << "Imported from " << getFirewallObject()->getName() << "\n"
<< srs << "-" << sre << ":" << drs << "-" << dre;
std::ostringstream nstr;
nstr << "udp " ;
if (srs!=0 || sre!=0) nstr << srs << "-" << sre << ":";
if (drs!=0 || dre!=0) nstr << drs << "-" << dre;
UDPService* s = UDPService::cast(
createObject(UDPService::TYPENAME, nstr.str()));
s->setSrcRangeStart(srs);
s->setSrcRangeEnd(sre);
s->setDstRangeStart(drs);
s->setDstRangeEnd(dre);
s->setComment(cstr.str());
all_objects[sstr.str()] = s;
*logger << "UDP Service object: " + nstr.str() + "\n";
return s;
}
FWObject* Importer::getTagService(const std::string &tagcode)
{
TagService *s = NULL;
std::ostringstream nstr, cstr, sstr;
nstr << "tag-" << tagcode;
sstr << "tag-" << tagcode;
cstr << "Imported from " << getFirewallObject()->getName() << "\n"
<< "mark " << tagcode;
if (all_objects.count(sstr.str())!=0)
return TagService::cast(all_objects[sstr.str()]);
s = TagService::cast(createObject(TagService::TYPENAME, nstr.str()));
assert(s!=NULL);
s->setCode(tagcode);
s->setComment(cstr.str());
all_objects[sstr.str()] = s;
*logger << "Tag Service object: " + nstr.str() + "\n";
return s;
}
FWObject* Importer::createICMPService()
{
int type, code;
std::istringstream s1(icmp_type), s2(icmp_code);
s1.exceptions(std::ios::failbit);
s2.exceptions(std::ios::failbit);
if (strip(icmp_type).empty()) type = -1;
else
{
try
{
s1 >> type;
} catch (std::exception& e)
{
// could not convert
type = -1;
markCurrentRuleBad(std::string("ICMP type '") + icmp_type + "' unknown");
}
}
if (strip(icmp_code).empty()) code = -1;
else
{
try
{
s2 >> code;
} catch (std::exception& e)
{
// could not convert
code = -1;
markCurrentRuleBad(std::string("ICMP code '") + icmp_code + "' unknown");
}
}
return getICMPService(type,code);
}
FWObject* Importer::createIPService()
{
// this assumes protocol is represented by a number
std::istringstream str(protocol);
str.exceptions(std::ios::failbit);
int proto_num;
try
{
str >> proto_num;
} catch (std::exception& e)
{
// could not convert protocol number
proto_num = 0;
markCurrentRuleBad(std::string("Protocol '") + protocol + "' unknown");
}
return getIPService(proto_num);
}
FWObject* Importer::createTCPService()
{
// Default implementation
//
// use src_port_spec, dst_port_spec
//
// here we assume src_port_spec and dst_port_spec are
// both numeric and represent a single port.
std::string name = "tcp " + src_port_spec + " " + dst_port_spec;
std::istringstream src_str(src_port_spec);
std::istringstream dst_str(dst_port_spec);
int sport, dport;
src_str >> sport;
dst_str >> dport;
return getTCPService(sport,sport,
dport,dport,
established,tcp_flags_mask,tcp_flags_comp);
}
FWObject* Importer::createUDPService()
{
// Default implementation
//
// use src_port_spec, dst_port_spec
//
// here we assume src_port_spec and dst_port_spec are
// both numeric and represent a single port.
std::string name = "udp " + src_port_spec + " " + dst_port_spec;
std::istringstream src_str(src_port_spec);
std::istringstream dst_str(dst_port_spec);
int sport, dport;
src_str >> sport;
dst_str >> dport;
return getUDPService(sport,sport,dport,dport);
}
FWObject* Importer::createGroupOfInterfaces(
const std::string &ruleset_name, std::list<std::string> &interfaces)
{
std::string name = "intf-" + ruleset_name;
// by including ruleset name (==acl name) into the signature we
// force import to create separate interface group for each access list
// even if interface set is the same as for some other access list.
// This decision is rather arbitrary but it feels less confusing
// compared to the case when interface groups cretaed from different
// access lists are merged. If they are merged, the name refers to one
// access list which looks weird in the GUI since rules may have been
// imported from another access list.
std::string sig = ruleset_name + "_";
std::for_each(interfaces.begin(), interfaces.end(), join(&sig, "_"));
if (fwbdebug)
qDebug() << QString("Interface group with name '%1', sig '%2'")
.arg(name.c_str()).arg(sig.c_str());
if (all_objects.count(sig)!=0) return all_objects[sig];
ObjectGroup *og = ObjectGroup::cast(createObject(ObjectGroup::TYPENAME, name));
for (std::list<std::string>::iterator j=interfaces.begin(); j!=interfaces.end(); ++j)
{
Interface *intf = all_interfaces[*j];
og->addRef(intf);
}
all_objects[sig] = og;
return og;
}
FWObject* Importer::createAddress(const std::string &addr,
const std::string &netmask)
{
std::string sig = std::string("addr-") + addr + "/" + netmask;
if (all_objects.count(sig)!=0) return all_objects[sig];
if ( netmask == InetAddr::getAllOnes().toString() )
{
string name;
try
{
InetAddr obj_addr(addr); // testing if string converts to an address
name = std::string("h-") + addr;
Address *a = Address::cast(createObject(IPv4::TYPENAME, name));
a->setAddress(obj_addr);
a->setNetmask(InetAddr(InetAddr::getAllOnes()));
string comment = "Imported from " + getFirewallObject()->getName() +
" " + addr + "/" + netmask;
a->setComment(comment);
all_objects[sig] = a;
*logger << "Address object: " + name + "\n";
return a;
} catch(FWException &ex)
{
// address text line can not be converted to ipv4 address.
// Since parsers do not understand ipv6 yet, assume this
// is a host address and create DNSName object
name = addr;
DNSName *da = DNSName::cast(createObject(DNSName::TYPENAME, name));
da->setSourceName(addr);
da->setRunTime(true);
string comment = "Imported from " + getFirewallObject()->getName() +
" " + addr;
da->setComment(comment);
all_objects[sig] = da;
*logger << "DNSName object: " + name + "\n";
return da;
}
} else
{
Network *net;
std::string name = std::string("net-") + addr + "/" + netmask;
net = Network::cast(createObject(Network::TYPENAME, name));
try
{
net->setAddress( InetAddr(addr) );
} catch (FWException &ex)
{
markCurrentRuleBad(
std::string("Error converting address '") + addr + "'");
}
try
{
net->setNetmask( InetAddr(netmask) );
} catch (FWException &ex)
{
if (netmask.find('.')!=std::string::npos)
{
// netmask has '.' in it but conversion failed.
markCurrentRuleBad(
std::string("Error converting netmask '") + netmask + "'");
} else
{
// no dot in netmask, perhaps it is specified by its length?
// if netmask is specified by length, need to use special
// constructor for class Netmask to convert
std::istringstream str(netmask);
str.exceptions(std::ios::failbit);
int nm_len;
try
{
str >> nm_len;
net->setNetmask( InetAddr(nm_len) );
} catch (std::exception& e)
{
// could not convert netmask as simple integer
markCurrentRuleBad(
std::string("Error converting netmask '") + netmask + "'");
}
}
}
string comment = "Imported from " + getFirewallObject()->getName() +
" " + addr + "/" + netmask;
net->setComment(comment);
all_objects[sig] = net;
*logger << "Network object: " + name + "\n";
return net;
}
return NULL;
}
FWObject* Importer::createAddressRange(const std::string &addr1,
const std::string &addr2)
{
std::string comment = "Imported from " + getFirewallObject()->getName() +
" " + addr1 + "-" + addr2;
std::string sig = std::string("ar-") + addr1 + "-" + addr2;
if (all_objects.count(sig)!=0) return all_objects[sig];
AddressRange *ar;
std::string name = std::string("range-") + addr1 + "-" + addr2;
ar = AddressRange::cast(createObject(AddressRange::TYPENAME, name));
try
{
ar->setRangeStart( InetAddr(addr1) );
} catch (FWException &ex)
{
markCurrentRuleBad(
std::string("Error converting address '") + addr1 + "'");
}
try
{
ar->setRangeEnd( InetAddr(addr2) );
} catch (FWException &ex)
{
markCurrentRuleBad(
std::string("Error converting address '") + addr2 + "'");
}
ar->setComment(comment);
all_objects[sig] = ar;
*logger << "AddressRange object: " + name + "\n";
return ar;
}
/**
* set color of the current rule (use red) and add comment
* to indicate that the rule could not be properly parsed
*/
void Importer::markCurrentRuleBad(const std::string &comment)
{
FWOptions *ropt = current_rule->getOptionsObject();
assert(ropt!=NULL);
ropt->setStr("color", getBadRuleColor());
if (!rule_comment.empty()) rule_comment += "\n";
rule_comment += comment;
//current_rule->setComment(comment);
QString err = QObject::tr("Parser error: Line %1: %2\n")
.arg(getCurrentLineNumber())
.arg(QString::fromUtf8(comment.c_str()));
*logger << err.toUtf8().constData();
error_counter++;
}
int Importer::countRules()
{
int n = 0;
std::map<const string, UnidirectionalRuleSet*>::iterator it;
for (it=all_rulesets.begin(); it!=all_rulesets.end(); ++it)
{
// rs_index is a string composed of the table name and chain name
// like "filter / FORWARD" or "mangle / PREROUTING"
// This string is created in IPTImporter::getUnidirRuleSet()
string rs_index = it->first;
UnidirectionalRuleSet* rs = it->second;
n += rs->ruleset->getRuleSetSize();
}
return n;
}
int Importer::countInterfaces()
{
if (haveFirewallObject())
{
Firewall *fw = Firewall::cast(getFirewallObject());
list<FWObject*> all_interfaces = fw->getByType(Interface::TYPENAME);
return all_interfaces.size();
} else
return 0;
}
QString Importer::noFirewallErrorMessage()
{
return QObject::tr(
"Could not find enough information in the data file "
"to create firewall object."
"\n\n"
);
}
QString Importer::noRulesErrorMessage()
{
return QObject::tr(
"Could not find enough information in the data file "
"to create any firewall rules."
"\n\n"
);
}
QString Importer::noInterfacesErrorMessage()
{
return QObject::tr(
"Could not find enough information in the data file "
"to create firewall interface objects."
"\n\n"
);
}
/*
* This is a common error message shown by the importer when it fails
* to create firewall object. Keeping it in the base class since it is
* used in the finalize() function of all importer classes.
*/
QString Importer::commonFailureErrorMessage()
{
return QObject::tr(
"Please check that the "
"file you are trying to import is in one of supported "
"formats. Currently fwbuilder can only import "
"iptables configuration saved with "
"'iptables-restore' command and Cisco routers (IOS) "
"configurations saved with 'show run' command. Import "
"of cisco ASA (PIX) configuration is not supported "
"at this time");
}
void Importer::addMessageToLog(const std::string &msg)
{
*logger << msg + "\n";
}