1
0
mirror of https://github.com/fwbuilder/fwbuilder synced 2026-03-23 11:47:24 +01:00
fwbuilder/src/libgui/DiscoveryDruid.cpp
2011-02-25 14:02:32 -08:00

2718 lines
76 KiB
C++

/*
Firewall Builder
Copyright (C) 2005, 2006 NetCitadel, LLC
Author: Vadim Kurland vadim@fwbuilder.org
Illiya Yalovoy <yalovoy@gmail.com>
$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.h"
#include "events.h"
#include <qradiobutton.h>
#include <qlineedit.h>
#include <qcheckbox.h>
#include <qcombobox.h>
#include <qspinbox.h>
#include <qtimer.h>
#include <qregexp.h>
#include <qlabel.h>
#include <qtextbrowser.h>
#include <qtextedit.h>
#include <qpushbutton.h>
#include <qfile.h>
#include <qfiledialog.h>
#include <qapplication.h>
#include <qprogressdialog.h>
#include <qlistview.h>
#include <qtextstream.h>
#include <qiodevice.h>
#include <qhostaddress.h>
#include <qhostinfo.h>
#include <qgroupbox.h>
#include <qmessagebox.h>
#include <QtDebug>
#include "DiscoveryDruid.h"
#include "ProjectPanel.h"
#include "interfaceProperties.h"
#include "interfacePropertiesObjectFactory.h"
#include <iostream>
#include <map>
#include <vector>
#include <set>
#include <memory>
#include "fwbuilder/HostsFile.h"
#include "fwbuilder/IPv4.h"
#include "fwbuilder/IPv6.h"
#include "fwbuilder/Host.h"
#include "fwbuilder/Network.h"
#include "fwbuilder/NetworkIPv6.h"
#include "fwbuilder/InetAddr.h"
#include "fwbuilder/InetAddrMask.h"
#include "fwbuilder/Inet6AddrMask.h"
#include "fwbuilder/Firewall.h"
#include "fwbuilder/Policy.h"
#include "fwbuilder/dns.h"
#include "fwbuilder/snmp.h"
#include "fwbuilder/Logger.h"
#include "FWBSettings.h"
#include "UserWorkflow.h"
#include "ObjectManipulator.h"
#include "FWWindow.h"
#include "IOSImporter.h"
#include "IPTImporter.h"
#include "PIXImporter.h"
using namespace std;
using namespace libfwbuilder;
DiscoveryDruid::DiscoveryDruid(QWidget *parent, bool start_with_import) :
QDialog(parent)
{
m_dialog = new Ui::DiscoveryDruid_q;
m_dialog->setupUi(this);
setControlWidgets(this, m_dialog->stackedWidget,
m_dialog->nextButton,
m_dialog->finishButton,
m_dialog->backButton,
m_dialog->cancelButton,
m_dialog->titleLabel);
QTextCursor cursor(m_dialog->discoverylog->textCursor());
normal_format = cursor.charFormat();
error_format = normal_format;
error_format.setForeground(QBrush(Qt::red));
error_format.setAnchorHref("http://somewhere.com");
error_format.setAnchor(true);
// weight must be between 0 and 99. Qt 4.4.1 does not seem to mind if
// it is >99 (just caps it) but older versions assert
error_format.setProperty(QTextFormat::FontWeight, 99);
warning_format = normal_format;
warning_format.setForeground(QBrush(Qt::blue));
warning_format.setProperty(QTextFormat::FontWeight, 99);
warning_format.setAnchor(true);
warning_format.setAnchorHref("http://somewhere.com");
dm_method = new QButtonGroup;
dm_method->addButton(m_dialog->dm_fromfile,0);
dm_method->addButton(m_dialog->dm_importdns,1);
dm_method->addButton(m_dialog->dm_usesnmp,2);
dm_method->addButton(m_dialog->dm_import_config,3);
connect(dm_method, SIGNAL( buttonClicked(int) ),
this, SLOT( changedDiscoveryMethod(int) ) );
connect(m_dialog->dnsfromlist, SIGNAL( clicked(bool) ),
this, SLOT( changedNameServer() ) );
connect(m_dialog->dnscustom, SIGNAL( clicked(bool) ),
this, SLOT( changedNameServer() ) );
connect(m_dialog->nameserverlist, SIGNAL( editTextChanged(QString) ),
this, SLOT( changedNameServer() ) );
connect(m_dialog->nameserverline, SIGNAL( textChanged(QString) ),
this, SLOT( changedNameServer() ) );
thread = NULL;
timer = new QTimer(this);
prg_timer = new QTimer(this);
unBar = NULL;
unProg = 0;
connect(prg_timer,SIGNAL(timeout()),this,SLOT(updatePrg()));
setDiscoveryMethod_file();
flt_obj = new Filter();
flt_obj_d = new FilterDialog(this);
flt_obj_d->setFilter(flt_obj);
flt_last = new Filter();
flt_last_d = new FilterDialog(this);
flt_last_d->setFilter(flt_last);
flt_net = new Filter();
flt_net_d = new FilterDialog(this);
flt_net_d->setFilter(flt_net);
assert(mw->activeProject()->db());
fillLibraries(m_dialog->libs, mw->activeProject()->db());
m_dialog->libs->setEditable(true);
m_dialog->libs->lineEdit()->setText(mw->getCurrentLib()->getName().c_str());
m_dialog->DNSprogress->hide();
m_dialog->DNSprogress_2->hide();
#ifndef HAVE_GOODLIBRESOLV
m_dialog->dm_importdns->hide();
m_dialog->snmpdnsparameters->hide();
#endif
#ifndef HAVE_LIBSNMP
m_dialog->dm_usesnmp->setEnabled(false);
#endif
restore();
importPlatformChanged(m_dialog->import_platform->currentIndex());
showPage(0);
setNextEnabled(0, true);
if (start_with_import)
{
m_dialog->dm_import_config->setDown(true);
setDiscoveryMethod_Import();
setAppropriate( 0, false );
// show the first page of the "import policy" track of the wizard
showPage( 2 );
setNextEnabled(2, false);
cancelButton->show();
}
prg_timer->start(100);
}
void DiscoveryDruid::nextClicked()
{
if (nextRelevant( currentPage() ) > -1)
showPage(nextRelevant( currentPage() ));
}
void DiscoveryDruid::backClicked()
{
if (previousRelevant( currentPage() ) > -1)
showPage(previousRelevant( currentPage() ));
}
void DiscoveryDruid::finishClicked()
{
QDialog::accept();
}
void DiscoveryDruid::cancelClicked()
{
QDialog::reject();
}
DiscoveryDruid::~DiscoveryDruid()
{
save();
delete flt_obj;
delete flt_last;
delete flt_net;
delete flt_obj_d;
delete flt_last_d;
delete flt_net_d;
delete m_dialog;
delete dm_method;
}
const char * DISCOVERY_DRUID_PREFIX="DiscoveryDruid/";
const char * DISCOVERY_DRUID_DISCOVERYMETHOD="DiscoveryMethod";
const char * DISCOVERY_DRUID_FILENAME ="Filename";
const char * DISCOVERY_DRUID_DOMAINNAME ="Domainname";
const char * DISCOVERY_DRUID_USELONGNAME ="UseLongName";
const char * DISCOVERY_DRUID_NAMESERVER ="NameServer";
const char * DISCOVERY_DRUID_DNSTIMEOUT ="DNSTimeout";
const char * DISCOVERY_DRUID_DNSRETRIES ="DNSRetries";
const char * DISCOVERY_DRUID_SEEDHOST ="SeedHost";
const char * DISCOVERY_DRUID_SNMPINADDR ="SNMPInAddr";
const char * DISCOVERY_DRUID_SNMPINMASK ="SNMPInMask";
const char * DISCOVERY_DRUID_SNMPRECURSIVE ="SNMPRecursive";
const char * DISCOVERY_DRUID_SNMPFOLLOWP2P ="SNMPFollowP2P";
const char * DISCOVERY_DRUID_SNMPINCLUDEUNNUMBERED="SnmpIncludeUnnumbered";
const char * DISCOVERY_DRUID_SNMPDODNS ="SNMPDoDNS";
const char * DISCOVERY_DRUID_SNMPCOMMUNITY ="SNMPCommunity";
const char * DISCOVERY_DRUID_SNMPRETRIES ="SNMPRetries";
const char * DISCOVERY_DRUID_SNMPTIMEOUT ="SNMPTimeout";
const char * DISCOVERY_DRUID_SNMPDNSRETRIES ="DNSRetries";
const char * DISCOVERY_DRUID_SNMPDNSTIMEOUT ="DNSTimeout";
const char * DISCOVERY_DRUID_SNMPDNSTHREADS ="SNMPDnsThreads";
const char * DISCOVERY_DRUID_IMPORRT_CONFIG_PLATFORM = "ImportPlatform";
void DiscoveryDruid::restore()
{
int i;
QString s;
//Restore from settings
dm_method->button(st->getInt(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_DISCOVERYMETHOD))->setChecked(true);
changedDiscoveryMethod(dm_method->checkedId());
//m_dialog->filename->setText(st->getStr(
// QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_FILENAME));
//m_dialog->domainname->setText(st->getStr(
// QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_DOMAINNAME));
m_dialog->uselongname->setChecked(st->getBool(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_USELONGNAME));
//m_dialog->nameserverline->setText(st->getStr(
// QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_NAMESERVER));
i=st->getInt(QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_DNSTIMEOUT);
m_dialog->dnstimeout->setValue((i)?i:2);
i=st->getInt(QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_DNSRETRIES);
m_dialog->dnsretries->setValue((i)?i:1);
m_dialog->seedhostname->setText(st->getStr(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SEEDHOST));
m_dialog->snmpinaddr->setText(st->getStr(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPINADDR));
m_dialog->snmpinmask->setText(st->getStr(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPINMASK));
m_dialog->snmprecursive->setChecked(st->getBool(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPRECURSIVE));
m_dialog->snmpfollowp2p->setChecked(st->getBool(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPFOLLOWP2P));
m_dialog->snmpincludeunnumbered->setChecked(st->getBool(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPINCLUDEUNNUMBERED));
m_dialog->snmpdodns->setChecked(st->getBool(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPDODNS));
s=st->getStr(QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPCOMMUNITY);
m_dialog->snmpcommunity->setText((s.isEmpty())?"public":s);
i=st->getInt(QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPRETRIES);
m_dialog->snmpretries->setValue((i)?i:1);
i=st->getInt(QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPTIMEOUT);
m_dialog->snmptimeout->setValue((i)?i:2);
i=st->getInt(QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPDNSRETRIES);
m_dialog->snmpdnsretries->setValue((i)?i:1);
i=st->getInt(QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPDNSTIMEOUT);
m_dialog->snmpdnstimeout->setValue((i)?i:2);
i=st->getInt(QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPDNSTHREADS);
m_dialog->snmpdnsthreads->setValue((i)?i:5);
m_dialog->import_platform->setCurrentIndex(st->getInt(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_IMPORRT_CONFIG_PLATFORM));
}
void DiscoveryDruid::save()
{
// Save to settings
st->setInt(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_DISCOVERYMETHOD,
dm_method->checkedId());
st->setBool(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_USELONGNAME,
m_dialog->uselongname->isChecked());
if (current_task==BT_DNS)
{
st->setInt(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_DNSTIMEOUT,
m_dialog->dnstimeout->value());
st->setInt(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_DNSRETRIES,
m_dialog->dnsretries->value());
}
else
{
st->setInt(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPDNSRETRIES,
m_dialog->snmpdnsretries->value());
st->setInt(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPDNSTIMEOUT,
m_dialog->snmpdnstimeout->value());
}
st->setStr(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SEEDHOST,
m_dialog->seedhostname->text());
st->setStr(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPINADDR,
m_dialog->snmpinaddr->text());
st->setStr(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPINMASK,
m_dialog->snmpinmask->text());
st->setBool(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPRECURSIVE,
m_dialog->snmprecursive->isChecked());
st->setBool(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPFOLLOWP2P,
m_dialog->snmpfollowp2p->isChecked());
st->setBool(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPINCLUDEUNNUMBERED,
m_dialog->snmpincludeunnumbered->isChecked());
st->setBool(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPDODNS,
m_dialog->snmpdodns->isChecked());
st->setStr(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPCOMMUNITY,
m_dialog->snmpcommunity->text());
st->setInt(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPRETRIES,
m_dialog->snmpretries->value());
st->setInt(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPTIMEOUT,
m_dialog->snmptimeout->value());
st->setInt(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_SNMPDNSTHREADS,
m_dialog->snmpdnsthreads->value());
st->setInt(
QString(DISCOVERY_DRUID_PREFIX) + DISCOVERY_DRUID_IMPORRT_CONFIG_PLATFORM,
m_dialog->import_platform->currentIndex());
}
void DiscoveryDruid::dnsFinish(QHostInfo host)
{
QList<QHostAddress> list = host.addresses();
unBar->hide();
if (userIsTyping)
{
//abandon the test result
if (current_task==BT_DNS)
{
changedNameServer();
}
else
{
changedSeedHost();
}
}
else
{
//get the test result
if (list.isEmpty())
{
QPalette palette = errMessage->palette();
palette.setColor(errMessage->foregroundRole(), Qt::darkRed);
errMessage->setPalette(palette);
errMessage->setText( "host name not found");
isSeedHostOK=false;
}
else
{
QPalette palette = errMessage->palette();
palette.setColor(errMessage->foregroundRole(), Qt::darkGreen);
errMessage->setPalette(palette);
errMessage->setText( "host name verified");
isSeedHostOK=true;
}
nextButton->setEnabled(isSNMPInclNetOK && isSeedHostOK);
}
}
void DiscoveryDruid::changedSelected( const int &page )
{
switch (page)
{
case 1: // Reading file in hosts format
{
setNextEnabled(page,false);
changedHostsFileName();
m_dialog->filename->setFocus();
break;
}
case 2: // import config
{
m_dialog->obj_name->setFocus();
setBackEnabled(page,true);
setFinishEnabled(page,false);
break;
}
case 3: // Import DNS zone
{
changedDomainName();
m_dialog->domainname->setFocus();
//setNextEnabled(page,false);
break;
}
case 4: // Name server
{
if (page>FromPage)
getNameServers();
disconnect(timer,SIGNAL(timeout()),0,0);
connect(timer,SIGNAL(timeout()),this,SLOT(checkHostName()));
changedNameServer();
m_dialog->nameserverline->setFocus();
//setNextEnabled(page,false);
break;
}
case 5: // Network discovery using SNMP
{
disconnect(timer,SIGNAL(timeout()),0,0);
connect(timer,SIGNAL(timeout()),this,SLOT(checkHostName()));
isSeedHostOK=false;
isSNMPInclNetOK=false;
changedSeedHost();
changedInclNet();
m_dialog->seedhostname->setFocus();
break;
}
case 6: // Network scan options
{
m_dialog->snmprecursive->setFocus();
//setNextEnabled(page,false);
break;
}
case 7: // SNMP and DNS reverse lookup queries parameters
{
checkSNMPCommunity();
m_dialog->snmpcommunity->setFocus();
break;
}
case 8: // Background process (import from hosts and from config file)
{
m_dialog->discoveryprogress->setValue(-1);
m_dialog->discoverylog->clear();
m_dialog->discoveryStopButton->setEnabled(true);
m_dialog->logSaveButton->setEnabled(false);
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents,100);
setNextEnabled(page, false);
cancelButton->hide();
setBackEnabled(page, false);
disconnect(timer, SIGNAL(timeout()), 0, 0);
connect(timer, SIGNAL(timeout()), this, SLOT(updateLog()));
timer->setSingleShot(false);
timer->start(1000);
startBackgroundProcess();
break;
}
case 9: // Networks
{
fillListOfNetworks();
fillNetworks();
backButton->setEnabled(false);
nextButton->setEnabled(m_dialog->networklist->count ()>0 || Objects.size()>0);
break;
}
case 10: // Objects
{
if (Networks.size()==0)
setBackEnabled(page,false);
fillListOfObjects();
fillObjects();
nextButton->setEnabled(m_dialog->objectlist->count ()>0 || m_dialog->networklist->count()>0);
break;
}
case 11: // Adjust Object type
{
setBackEnabled(page,true);
fillTypeChangingList();
break;
}
case 12: // Target library
{
break;
}
case 13: // Objects creation ...
{
setBackEnabled(page,false);
cancelButton->hide();
createRealObjects();
setFinishEnabled(page,true);
finishButton->setFocus();
break;
}
default : {}
}
FromPage=page;
}
void DiscoveryDruid::startBackgroundProcess()
{
switch (current_task)
{
case BT_HOSTS:
case BT_IMPORT:
{
m_dialog->discoveryprogress->setMaximum(100);
m_dialog->discoveryprogress->setValue(0);
m_dialog->discoveryprogress->setEnabled(false);
m_dialog->discoveryStopButton->setEnabled(false);
break;
}
case BT_DNS:
case BT_SNMP:
{
m_dialog->discoveryprogress->setMaximum(0);
m_dialog->discoveryprogress->setValue(-1);
break;
}
default:
{}
}
switch (current_task)
{
case BT_HOSTS: startHostsScan(); break;
case BT_DNS: startDNSScan(); break;
case BT_SNMP: startSNMPScan(); break;
case BT_IMPORT: startConfigImport(); break;
default:
{}
}
}
void DiscoveryDruid::browseHostsFile()
{
QString dir;
dir=st->getWDir();
if (dir.isEmpty()) dir=st->getOpenFileDir();
if (dir.isEmpty()) dir="~";
QString s = QFileDialog::getOpenFileName(
this,
"Choose a file",
dir,
"All files (*)");
if (!s.isEmpty())
{
m_dialog->filename->setText(s);
}
}
void DiscoveryDruid::browseForImport()
{
QString dir;
dir=st->getWDir();
if (dir.isEmpty()) dir=st->getOpenFileDir();
if (dir.isEmpty()) dir="~";
QString s = QFileDialog::getOpenFileName(
this,
"Choose a file",
dir,
"All files (*)");
if (!s.isEmpty())
{
m_dialog->import_filename->setText(s);
}
}
void DiscoveryDruid::updatePrg()
{
if (unBar!=NULL)
{
unBar->setValue(unProg++);
}
}
void DiscoveryDruid::getNameServers()
{
// this is not supported anymore since all resolver functions
// have been removed from class DNS
m_dialog->nameserverlist->setEnabled(false);
m_dialog->dnsfromlist->setEnabled(false);
m_dialog->dnscustom->setChecked(true);
}
void DiscoveryDruid::setDiscoveryMethod_file()
{
current_task=BT_HOSTS;
m_dialog->processname->setText(tr("Hosts file parsing ..."));
for (int i=0;i<WIZARD_PAGES;i++)
{
setAppropriate( i, WIZARD_FILE_PAGES[i]);
}
}
void DiscoveryDruid::setDiscoveryMethod_DNS()
{
m_dialog->processname->setText(tr("DNS zone transfer ..."));
current_task=BT_DNS;
for (int i=0;i<WIZARD_PAGES;i++)
{
setAppropriate( i, WIZARD_DNS_PAGES[i]);
}
}
void DiscoveryDruid::setDiscoveryMethod_SNMP()
{
m_dialog->processname->setText(tr("Network discovery using SNMP ..."));
current_task=BT_SNMP;
for (int i=0;i<WIZARD_PAGES;i++)
{
setAppropriate( i, WIZARD_SNMP_PAGES[i]);
}
}
void DiscoveryDruid::setDiscoveryMethod_Import()
{
m_dialog->processname->setText(tr("Import configuration from file ..."));
current_task=BT_IMPORT;
for (int i=0;i<WIZARD_PAGES;i++)
{
setAppropriate( i, WIZARD_IMPORT_PAGES[i]);
}
}
void DiscoveryDruid::changedDiscoveryMethod(int c)
{
if (fwbdebug)
qDebug("DiscoveryDruid::changedDiscoveryMethod c=%d",c);
switch (c)
{
case 0:
{
setDiscoveryMethod_file();
break;
}
case 1:
{
setDiscoveryMethod_DNS();
break;
}
case 2:
{
setDiscoveryMethod_SNMP();
break;
}
case 3:
{
setDiscoveryMethod_Import();
break;
}
default : {}
}
}
void DiscoveryDruid::startHostsScan()
{
if (thread!=NULL)
{
delete thread;
}
thread = new HostsFileImport(m_dialog->filename->text());
thread->setTargetWidget(this);
thread->start();
}
void DiscoveryDruid::startConfigImport()
{
if (thread!=NULL)
{
delete thread;
}
QFile cf( m_dialog->import_filename->text() );
if (cf.open( QIODevice::ReadOnly ) )
{
QTextStream stream(&cf);
QString s = stream.readAll();
cf.close();
std::string *buffer = new std::string( s.toLatin1().constData() );
//if (fwbdebug) qDebug(buffer->c_str());
// count lines, gather some general stats on the config file.
std::string::size_type pos, n;
pos = 0;
int line_count = 0;
while ( (n=buffer->find('\n', pos))!=std::string::npos)
{
line_count++;
pos = n+1;
}
m_dialog->discoveryprogress->setMaximum(line_count);
// need to pick right platform string based on
// m_dialog->import_platform->currentItem()
string platform = "";
switch (m_dialog->import_platform->currentIndex())
{
case 0: platform = "iosacl"; break;
case 1: platform = "iptables"; break;
case 2: platform = "pix"; break;
}
//
// ConfigImport "owns" buffer - it is deleted
// in destructor of ConfigImport
//
thread = new ConfigImport(buffer, platform, m_dialog->obj_name->text().toStdString());
thread->setTargetWidget(this);
thread->start();
wfl->registerFlag(UserWorkflow::IMPORT, true);
} else
{
QMessageBox::critical(this, tr("Discovery error"),
tr("Could not open file %1").arg(m_dialog->import_filename->text()));
setBackEnabled(currentPage(),true);
}
}
InetAddr DiscoveryDruid::getNS()
{
string ns;
if (m_dialog->dnscustom->isChecked())
{
ns=m_dialog->nameserverline->text().toLatin1().constData();
try
{
return InetAddr(ns);
} catch (FWException &ex)
{
/* perhaps not address but host name */
list<InetAddr> addr;
try
{
addr=DNS::getHostByName(ns);
} catch (FWException &ex)
{
return InetAddr();
}
return addr.front();
}
}
return NameServers[m_dialog->nameserverlist->currentText()];
}
void DiscoveryDruid::startDNSScan()
{
// this is not supported since all resolver functions have been
// removed from class DNS
}
InetAddr DiscoveryDruid::getSeedHostAddress()
{
if (fwbdebug)
qDebug() <<
QString("DiscoveryDruid::getSeedHostAddress(): Seed host name %1").
arg(m_dialog->seedhostname->text());
libfwbuilder::InetAddr seed_host_addr;
if (!m_dialog->seedhostname->text().isEmpty())
{
try
{
QString a = getAddrByName( m_dialog->seedhostname->text(), AF_INET);
if (fwbdebug)
qDebug() <<
QString("DiscoveryDruid::getSeedHostAddress() address: %1").
arg(a);
return InetAddr( a.toLatin1().constData() );
} catch(const FWException &ex)
{
}
try
{
seed_host_addr = InetAddr(
m_dialog->seedhostname->text().toLatin1().constData());
return seed_host_addr;
} catch(const FWException &ex)
{
}
}
return seed_host_addr;
}
void DiscoveryDruid::changedDomainName()
{
if (m_dialog->domainname->text().isEmpty())
{
nextButton->setEnabled(false);
}
else
{
nextButton->setEnabled(true);
}
}
void DiscoveryDruid::changedNameServer()
{
userIsTyping=true;
isSNMPInclNetOK=true;
if(m_dialog->dnscustom->isChecked())
{
nextButton->setEnabled(false);
QString s=m_dialog->nameserverline->text();
HostName=s;
if (s.isEmpty())
{
timer->stop();
m_dialog->DNSprogress_2->hide();
QPalette palette = m_dialog->nameserver_error->palette();
palette.setColor(m_dialog->nameserver_error->foregroundRole(), Qt::darkRed);
m_dialog->nameserver_error->setPalette(palette);
m_dialog->nameserver_error->setText("Enter valid host name or address.");
nextButton->setEnabled(false);
return;
}
if(isInetAddr(s))
{
timer->stop();
m_dialog->DNSprogress_2->hide();
QString rs=testInetAddr(s);
if (rs.isEmpty())
{
m_dialog->nameserver_error->setText(" ");
nextButton->setEnabled(true);
}
else
{
QPalette palette = m_dialog->nameserver_error->palette();
palette.setColor(m_dialog->nameserver_error->foregroundRole(), Qt::darkRed);
m_dialog->nameserver_error->setPalette(palette);
m_dialog->nameserver_error->setText(rs);
nextButton->setEnabled(false);
}
}
else
{
unBar=m_dialog->DNSprogress_2;
unBar->show();
timer->setSingleShot(true);
timer->start(1000);
errMessage=m_dialog->nameserver_error;
userIsTyping=false;
QPalette palette = errMessage->palette();
palette.setColor(errMessage->foregroundRole(), Qt::black);
errMessage->setPalette(palette);
errMessage->setText("DNS resolution in progress...");
unProg = 0;
}
}
else
{
timer->stop();
m_dialog->DNSprogress_2->hide();
m_dialog->nameserver_error->setText(" ");
nextButton->setEnabled(true);
}
}
void DiscoveryDruid::typedCustomNS()
{
if(!m_dialog->dnscustom->isChecked())
{
m_dialog->dnscustom->setChecked(true);
}
}
bool DiscoveryDruid::isInetAddr(const QString s)
{
QRegExp r=QRegExp("^(\\d|\\.)+$",Qt::CaseInsensitive); //non wildcard
return r.exactMatch(s);
}
QString DiscoveryDruid::testInetAddr(const QString s)
{
QString res;
QRegExp r=QRegExp("^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$",Qt::CaseInsensitive); //non wildcard
if (r.exactMatch(s))
{
try
{
InetAddr(s.toLatin1().constData());
} catch(const FWException &ex)
{
res=ex.toString().c_str();
}
}
else
{
res="Wrong IPv4 format";
}
return res;
}
void DiscoveryDruid::changedHostsFileName()
{
QFile f;
f.setFileName(m_dialog->filename->text());
if (f.exists())
{
setNextEnabled(currentPage(),true);
}
else
{
setNextEnabled(currentPage(),false);
}
}
void DiscoveryDruid::changedSNMPOptions()
{
}
void DiscoveryDruid::stopBackgroundProcess()
{
if (fwbdebug)
qDebug("stopBackgroundProcess bop=%p isRunning=%d",
bop,(bop!=NULL)?bop->isRunning():-1);
if (bop!=NULL && bop->isRunning())
{
addToLog("Terminating task. Please wait...");
bop->stop_operation();
m_dialog->discoveryStopButton->setEnabled(false);
}
}
void DiscoveryDruid::addNetwork()
{
int count = m_dialog->networkresultlist->count();
int upd_max=(count > 10)?count/10:1;
int updc=upd_max;
int t=0;
QProgressDialog pd(tr("Adding objects ..."), tr("Cancel"), 0, count,this);
QListWidgetItem* item=(QListWidgetItem*)m_dialog->networkresultlist->item(0);
int i = 0;
while (item)
{
if (item->isSelected())
{
QString k=item->text();
if (!Networks[k].isSelected)
{
Networks[k].isSelected=true;
m_dialog->networklist->addItem(item->text());
}
}
i++;
item=(QListWidgetItem*)m_dialog->networkresultlist->item(i);
if (updc--<=0)
{
pd.setValue(t);
qApp->processEvents();
if (pd.wasCanceled())
{
break;
}
updc=upd_max;
}
t++;
}
nextButton->setEnabled(m_dialog->networklist->count ()>0 || Objects.size()>0);
}
void DiscoveryDruid::removeNetwork()
{
QListWidgetItem* item1=m_dialog->networklist->item(0);
QListWidgetItem* item2;
while (item1!=0)
{
item2=m_dialog->networklist->item(
m_dialog->networklist->row(item1)+1);
if (item1->isSelected())
{
Networks[item1->text()].isSelected=false;
delete item1;
}
item1=item2;
}
nextButton->setEnabled(m_dialog->networklist->count ()>0 || Objects.size()>0);
}
void DiscoveryDruid::setNetworkFilter()
{
flt_net_d->exec();
fillListOfNetworks();
}
void DiscoveryDruid::removeNetworkFilter()
{
flt_net->clear();
fillListOfNetworks();
}
void DiscoveryDruid::addObject()
{
int count = m_dialog->objectresultlist->count();
int upd_max=(count > 10)?count/10:1;
int updc=upd_max;
int t=0;
QProgressDialog pd(tr("Adding objects ..."),
tr("Cancel"), 0, count,this);
QListWidgetItem* item=(QListWidgetItem*)m_dialog->objectresultlist->item(0);
int i = 0;
while (item)
{
if (item->isSelected())
{
QString k=item->text();
if (!Objects[k].isSelected)
{
Objects[k].isSelected=true;
m_dialog->objectlist->addItem(item->text());
}
}
i++;
item=(QListWidgetItem*)m_dialog->objectresultlist->item(i);
if (updc--<=0)
{
pd.setValue(t);
qApp->processEvents();
if (pd.wasCanceled())
{
break;
}
updc=upd_max;
}
t++;
}
nextButton->setEnabled(m_dialog->objectlist->count ()>0 || m_dialog->networklist->count()>0);
}
void DiscoveryDruid::removeObject()
{
QListWidgetItem* item1=m_dialog->objectlist->item(0);
QListWidgetItem* item2;
while (item1!=0)
{
item2=m_dialog->objectlist->item(
m_dialog->objectlist->row(item1)+1);
if (item1->isSelected())
{
Objects[item1->text()].isSelected=false;
delete item1;
}
item1=item2;
}
nextButton->setEnabled(m_dialog->objectlist->count ()>0 || m_dialog->networklist->count()>0);
}
void DiscoveryDruid::setLastFilter()
{
flt_last_d->exec();
fillTypeChangingList();
}
void DiscoveryDruid::setObjectFilter()
{
flt_obj_d->exec();
fillListOfObjects();
}
void DiscoveryDruid::removeLastFilter()
{
flt_last->clear();
fillTypeChangingList();
}
void DiscoveryDruid::removeObjectFilter()
{
flt_obj->clear();
fillListOfObjects();
}
void DiscoveryDruid::selectAllResNets()
{
m_dialog->networkresultlist->selectAll();
}
void DiscoveryDruid::selectAllNets()
{
m_dialog->networklist->selectAll();
}
void DiscoveryDruid::selectAllResObjs()
{
m_dialog->objectresultlist->selectAll();
}
void DiscoveryDruid::selectAllObjs()
{
m_dialog->objectlist->selectAll();
}
void DiscoveryDruid::fillNetworks()
{
ObjectDescriptor buf;
m_dialog->networklist->clear();
bool f=false;
QMap<QString,ObjectDescriptor >::iterator i;
for(i=Networks.begin(); i!=Networks.end(); ++i)
{
buf=i.value();
if (buf.isSelected)
{
m_dialog->networklist->addItem(new QListWidgetItem(i.key()));
f=true;
}
}
nextButton->setEnabled(f);
}
void DiscoveryDruid::fillObjects()
{
ObjectDescriptor buf;
m_dialog->objectlist->clear();
bool f=false;
QMap<QString,ObjectDescriptor >::iterator i;
for(i=Objects.begin(); i!=Objects.end(); ++i)
{
buf=i.value();
if (buf.isSelected)
{
m_dialog->objectlist->addItem(new QListWidgetItem(i.key()));
f=true;
}
}
nextButton->setEnabled(f);
}
void DiscoveryDruid::fillTypeChangingList()
{
ObjectDescriptor buf;
m_dialog->typeChangingList->clear();
QMap<QString,ObjectDescriptor >::iterator i;
for(i=Objects.begin(); i!=Objects.end(); ++i)
{
buf=i.value();
if (buf.isSelected)
{
QString ins;
if ( flt_last->test(buf) )
{
ins=(buf.interfaces.size())?
QString("%1").arg(buf.interfaces.size()):"";
QStringList sl;
sl << buf.toString().c_str() << ins << buf.type.c_str();
new QTreeWidgetItem( m_dialog->typeChangingList, sl );
}
}
}
m_dialog->typeChangingList->resizeColumnToContents(0);
m_dialog->typeChangingList->resizeColumnToContents(1);
}
void DiscoveryDruid::loadDataFromDNS()
{
// this is not supported since all resolver functions have been
// removed from class DNS
}
void DiscoveryDruid::loadDataFromFile()
{
m_dialog->objectresultlist->clear();
int t=0;
HostsFileImport *himport = dynamic_cast<HostsFileImport*>(thread);
assert(himport!=NULL);
int count = himport->hosts.size();
if (count > 0)
{
int upd_max=(count > 10)?count/10:1;
int updc=upd_max;
QProgressDialog pd(tr("Prepare objects ..."), tr("Cancel"), 0, count,this);
vector<ObjectDescriptor>::iterator i;
for(i = himport->hosts.begin(); i != himport->hosts.end(); ++i)
{
if (i->type.empty())
{
i->type=IPv4::TYPENAME;
}
i->isSelected=false;
Objects[i->toString().c_str()] = *i;
if (updc--<=0)
{
pd.setValue(t);
qApp->processEvents();
if (pd.wasCanceled())
{
break;
}
updc=upd_max;
}
t++;
}
}
}
void DiscoveryDruid::loadDataFromImporter()
{
ConfigImport *confimp = dynamic_cast<ConfigImport*>(thread);
assert(confimp!=NULL);
Importer *imp = confimp->getImporterObject();
if (imp!=NULL)
{
Firewall *fw = imp->finalize();
qApp->processEvents(); // to flush the log
if (fw) // fw can be NULL if import was uncussessful
{
ProjectPanel *pp = mw->activeProject();
QString filename = pp->getFileName();
//pp->m_panel->om->reload();
//pp->m_panel->om->autoRenameChildren(fw, "");
QCoreApplication::postEvent(mw, new reloadObjectTreeEvent(filename));
if (mw->isEditorVisible())
QCoreApplication::postEvent(
mw, new openObjectInEditorEvent(filename, fw->getId()));
QCoreApplication::postEvent(
mw, new showObjectInTreeEvent(filename, fw->getId()));
// Open first created Policy ruleset object
FWObject *first_policy = fw->getFirstByType(Policy::TYPENAME);
if (first_policy)
QCoreApplication::postEvent(
mw, new openRulesetEvent(filename, first_policy->getId()));
}
}
}
void DiscoveryDruid::saveScanLog()
{
QString dir;
dir=st->getWDir();
if (dir.isEmpty()) dir=st->getOpenFileDir();
if (dir.isEmpty()) dir="~";
QString s = QFileDialog::getSaveFileName(
this,
"Choose a file",
dir,
"Text file (*.txt)");
if (!s.isEmpty())
{
if (s.endsWith(".txt"))
{
s+=".txt";
}
QFile f(s);
if (f.open(QIODevice::WriteOnly))
{
if (fwbdebug)
{
qDebug("Saving crawler log to file: %d chars",
m_dialog->discoverylog->toPlainText().length());
qDebug("--------------------------------");
}
QTextStream strm(&f);
QString txt = m_dialog->discoverylog->toPlainText();
strm << txt << endl;
if (fwbdebug) qDebug("%s",txt.toAscii().constData());
if (fwbdebug)
qDebug("--------------------------------");
f.close();
}
}
}
void DiscoveryDruid::startSNMPScan()
{
#ifdef HAVE_LIBSNMP
bool use_incl=!m_dialog->snmpinaddr->text().isEmpty() && !m_dialog->snmpinmask->text().isEmpty();
if (use_incl)
{
try
{
InetAddrMask in(
InetAddr(m_dialog->snmpinaddr->text().toLatin1().constData()),
InetAddr(m_dialog->snmpinmask->text().toLatin1().constData())
);
include_networks.push_back(in);
}
catch (const FWException &ex)
{
//TODO: do something usefull
}
}
libfwbuilder::SNMPCrawler *q = new SNMPCrawler();
q->init(getSeedHostAddress(),
m_dialog->snmpcommunity->text().toLatin1().constData(),
m_dialog->snmprecursive->isChecked(),
false,
m_dialog->snmpfollowp2p->isChecked(),
0,
m_dialog->snmpretries->value(),
1000000L*m_dialog->snmptimeout->value(),
0,
0,
(use_incl) ? &include_networks : NULL);
m_dialog->discoveryprogress->setMaximum(0);
unBar = m_dialog->discoveryprogress;
bop=q;
try
{
logger = bop->start_operation();
if (fwbdebug) logger->copyToStderr();
addToLog("Collecting data ...");
disconnect(timer, SIGNAL(timeout()), 0, 0);
connect(timer, SIGNAL(timeout()), this, SLOT(updateLog()));
timer->setSingleShot(false);
timer->start(100);
} catch(const FWException &ex)
{
delete q;
q=NULL;
}
#endif
}
void DiscoveryDruid::loadDataFromCrawler()
{
#ifdef HAVE_LIBSNMP
SNMPCrawler *q=(SNMPCrawler*)bop;
Objects.clear();
Networks.clear();
set<InetAddrMask*>::iterator m;
set<InetAddrMask*> discovered_networks = q->getNetworks();
if (fwbdebug)
qDebug() << QString("got %1 networks").arg(discovered_networks.size());
for (m=discovered_networks.begin(); m!=discovered_networks.end(); ++m)
{
ObjectDescriptor od;
InetAddrMask *net = *m;
if (fwbdebug)
qDebug() << QString("network %1").arg(net->toString().c_str());
// if address in *m is ipv6, recreate it as Inet6AddrMask and
// use type NetworkIPv6
if (net->getAddressPtr()->isV6())
{
Inet6AddrMask in6am(*(net->getAddressPtr()),
*(net->getNetmaskPtr()));
od.sysname = in6am.toString(); // different from ipv6
od.type = NetworkIPv6::TYPENAME;
} else
{
od.sysname = net->toString();
od.type = Network::TYPENAME;
}
od.addr = *(net->getAddressPtr());
od.netmask = *(net->getNetmaskPtr());
od.isSelected = false;
Networks[od.sysname.c_str()]= od;
}
map<InetAddr, CrawlerFind> t = q->getAllIPs();
if (fwbdebug)
qDebug() << QString("got %1 addresses").arg(t.size());
m_dialog->discoveryprogress->setMaximum( t.size() );
m_dialog->discoveryprogress->setValue(0);
int cntr = 0;
map<InetAddr, CrawlerFind>::iterator j;
for(j = t.begin(); j!=t.end(); ++j,++cntr)
{
m_dialog->discoveryprogress->setValue( cntr );
ObjectDescriptor od( (*j).second );
od.addr = (*j).first;
od.type=(od.interfaces.size()>1)?
(Host::TYPENAME):(IPv4::TYPENAME);
od.isSelected=false;
if (od.sysname.empty())
{
od.sysname = string("h-") + od.addr.toString();
if (m_dialog->snmpdodns->isChecked())
{
QString hostName = getNameByAddr( od.addr.toString().c_str() );
if (!hostName.isEmpty())
od.sysname = hostName.toLatin1().constData();
}
addToLog(
QString(od.addr.toString().c_str()) + " : " + od.sysname.c_str());
}
Objects[od.toString().c_str()]=od;
set<string>::iterator si;
for(si=od.dns_info.aliases.begin();
si!=od.dns_info.aliases.end();
++si)
{
od.sysname=(*si);
Objects[od.toString().c_str()]=od;
}
}
#endif
}
void DiscoveryDruid::fillListOfNetworks()
{
m_dialog->networkresultlist->clear();
int t=0;
int count = Networks.size();
if (count > 0)
{
int upd_max=(count > 10)?count/10:1;
int updc=upd_max;
QProgressDialog pd(tr("Copying results ..."), tr("Cancel"), 0, count,this);
QMap<QString, ObjectDescriptor>::iterator i;
for (i=Networks.begin(); i!=Networks.end(); ++i)
{
if ( flt_net->test(i.value()) )
{
m_dialog->networkresultlist->addItem(new QListWidgetItem(i.key()));
if (updc--<=0)
{
pd.setValue(t);
qApp->processEvents();
if (pd.wasCanceled())
{
break;
}
updc=upd_max;
}
}
t++;
}
}
}
void DiscoveryDruid::fillListOfObjects()
{
m_dialog->objectresultlist->clear();
int t=0;
int count = Objects.size();
if (count > 0)
{
int upd_max=(count > 10)?count/10:1;
int updc=upd_max;
QProgressDialog pd(tr("Copying results ..."),
tr("Cancel"), 0,count,this);
QMap<QString,ObjectDescriptor >::iterator i;
for(i=Objects.begin(); i!=Objects.end(); ++i)
{
if ( flt_obj->test(i.value()) )
{
m_dialog->objectresultlist->addItem(new QListWidgetItem(i.key()));
if (updc--<=0)
{
pd.setValue(t);
qApp->processEvents();
if (pd.wasCanceled())
{
break;
}
updc=upd_max;
}
}
t++;
}
}
}
void DiscoveryDruid::customEvent(QEvent *event)
{
int evtype=(int)event->type();
if (evtype == ProgressEv)
{
ProgressEvent *e = (ProgressEvent*)event;
m_dialog->discoveryprogress->setValue(e->value);
} else if (evtype == DoneEv)
{
cancelButton->show();
timer->stop();
disconnect(timer,SIGNAL(timeout()),0,0);
updateLog();
m_dialog->logSaveButton->setEnabled(true);
// actually create objects
switch (current_task)
{
case BT_HOSTS:
loadDataFromFile();
break;
case BT_IMPORT:
loadDataFromImporter();
break;
default:
break;
}
thread->wait();
QString er = thread->getError();
delete thread;
thread=NULL;
switch (current_task)
{
case BT_HOSTS:
if (Objects.size()>0)
{
nextButton->setDefault(true);
nextButton->setFocus();
nextButton->setEnabled(true);
backButton->setEnabled(false);
}
else
{
backButton->setEnabled(true);
nextButton->setEnabled(false);
}
break;
case BT_IMPORT:
setFinishEnabled(currentPage(),true);
finishButton->setFocus();
break;
default:
break;
}
}
}
void DiscoveryDruid::updateLog()
{
if (fwbdebug) qDebug("DiscoveryDruid::updateLog");
if (current_task==BT_HOSTS || current_task==BT_IMPORT)
{
QString buf;
if (thread!=NULL)
{
while(thread->Log->ready())
{
buf = thread->Log->getLine().c_str();
addToLog(buf);
}
}
}
else if (current_task==BT_SNMP)
{
if (monitorOperation() > 0)
{
//m_dialog->discoveryprogress->setValue(prg++);
}
else
{
timer->stop();
disconnect(timer,SIGNAL(timeout()),0,0);
if (fwbdebug) qDebug("Crawler finished");
loadDataFromCrawler();
cancelButton->show();
FWException * ex=bop->get_latest_error();
if (ex!=NULL)
{
QMessageBox::critical(this,
tr("Discovery error"),
ex->toString().c_str());
}
if (Objects.size()>0 || Networks.size()>0)
{
if (Networks.size()==0) setAppropriate( 8,0);
nextButton->setEnabled(true);
nextButton->setDefault(true);
nextButton->setFocus();
backButton->setEnabled(false);
}
else
{
nextButton->setEnabled(false);
backButton->setEnabled(true);
}
m_dialog->logSaveButton->setEnabled(true);
delete bop;
bop=NULL;
unBar=NULL;
m_dialog->discoveryprogress->setMaximum(100);
m_dialog->discoveryprogress->setValue(100);
m_dialog->discoveryStopButton->setEnabled(false);
}
}
else if (current_task==BT_DNS)
{
if (monitorOperation() > 0)
{
//m_dialog->discoveryprogress->setMaximum(0);
//m_dialog->discoveryprogress->setValue(
// m_dialog->discoveryprogress->progress()+1);
}
else
{
timer->stop();
disconnect(timer,SIGNAL(timeout()),0,0);
loadDataFromDNS();
cancelButton->show();
FWException * ex=bop->get_latest_error();
if (ex!=NULL)
{
QMessageBox::critical(this, tr("Discovery error"),
ex->toString().c_str());
}
if (Objects.size()>0)
{
nextButton->setEnabled(true);
nextButton->setDefault(true);
nextButton->setFocus();
backButton->setEnabled(false);
}
else
{
nextButton->setEnabled(false);
backButton->setEnabled(true);
}
m_dialog->logSaveButton->setEnabled(true);
delete bop;
bop=NULL;
unBar=NULL;
m_dialog->discoveryprogress->setMaximum(100);
m_dialog->discoveryprogress->setValue(100);
m_dialog->discoveryStopButton->setEnabled(false);
}
}
}
void DiscoveryDruid::addToLog(const QString &buf)
{
if (buf.isEmpty()) return;
foreach(QString line, buf.trimmed().split("\n"))
{
QTextCharFormat format = normal_format;
if (line.contains("Parser error"))
format = error_format;
if (line.contains("SNMP error, status 2 Timeout"))
format = warning_format;
QString txt = line;
while (!txt.isEmpty() && (txt.endsWith("\n") || txt.endsWith("\r")))
txt.chop(1);
if (format == error_format || format == warning_format)
format.setAnchorHref(txt);
QTextCursor cursor = m_dialog->discoverylog->textCursor();
cursor.insertBlock();
cursor.insertText(txt, format);
}
m_dialog->discoverylog->ensureCursorVisible();
}
void DiscoveryDruid::changedSeedHost()
{
m_dialog->seedhosterror_message->setText(" ");
userIsTyping = true;
errMessage = m_dialog->seedhosterror_message;
HostName = m_dialog->seedhostname->text();
if (HostName.isEmpty())
{
timer->stop();
m_dialog->DNSprogress->hide();
QPalette palette = m_dialog->seedhosterror_message->palette();
palette.setColor(
m_dialog->seedhosterror_message->foregroundRole(), Qt::darkRed);
m_dialog->seedhosterror_message->setPalette(palette);
m_dialog->seedhosterror_message->setText(
"Enter a valid host name or address.");
isSeedHostOK=false;
}
else
{
if(isInetAddr(HostName))
{ // seems to be an IP Address
m_dialog->DNSprogress->hide();
timer->stop();
QRegExp r = QRegExp(
"^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$",
Qt::CaseInsensitive); //non wildcard
if (r.exactMatch(HostName))
{
try
{
InetAddr(HostName.toLatin1().constData());
QPalette palette =
m_dialog->seedhosterror_message->palette();
palette.setColor(
m_dialog->seedhosterror_message->foregroundRole(),
Qt::darkGreen);
m_dialog->seedhosterror_message->setPalette(palette);
m_dialog->seedhosterror_message->setText(
"Address verified");
isSeedHostOK=true;
} catch(const FWException &ex)
{
QPalette palette =
m_dialog->seedhosterror_message->palette();
palette.setColor(
m_dialog->seedhosterror_message->foregroundRole(),
Qt::darkRed);
m_dialog->seedhosterror_message->setPalette(palette);
m_dialog->seedhosterror_message->setText(
ex.toString().c_str());
// need to return focus to the input field in case of error
//m_dialog->seedhostname->setFocus();
isSeedHostOK=false;
}
}
else
{
QPalette palette = m_dialog->seedhosterror_message->palette();
palette.setColor(
m_dialog->seedhosterror_message->foregroundRole(),
Qt::darkRed);
m_dialog->seedhosterror_message->setPalette(palette);
m_dialog->seedhosterror_message->setText("Wrong IPv4 format");
isSeedHostOK=false;
}
}
else
{// it looks like a DNS name
isSeedHostOK = false;
QPalette palette = m_dialog->seedhosterror_message->palette();
palette.setColor(
m_dialog->seedhosterror_message->foregroundRole(), Qt::black);
m_dialog->seedhosterror_message->setPalette(palette);
m_dialog->seedhosterror_message->setText(
"DNS resolution in progress...");
unProg = 0;
unBar=m_dialog->DNSprogress;
errMessage=m_dialog->seedhosterror_message;
m_dialog->DNSprogress->show();
timer->setSingleShot(true);
timer->start(1000);
}
}
nextButton->setEnabled(isSNMPInclNetOK && isSeedHostOK);
}
void DiscoveryDruid::changedInclNet()
{
setNextEnabled(currentPage(),false);
m_dialog->confineerror_message->setText(" ");
bool use_incl=!m_dialog->snmpinaddr->text().isEmpty() && !m_dialog->snmpinmask->text().isEmpty();
if (use_incl)
{
try
{
InetAddr a(m_dialog->snmpinaddr->text().toLatin1().constData());
InetAddr n(m_dialog->snmpinmask->text().toLatin1().constData());
InetAddrMask(a,n);
m_dialog->confineerror_message->setText(" ");
isSNMPInclNetOK=true;
} catch (const FWException &ex)
{
isSNMPInclNetOK=false;
m_dialog->confineerror_message->setText(ex.toString().c_str());
}
}
else
{
if (!m_dialog->snmpinaddr->text().isEmpty() || !m_dialog->snmpinmask->text().isEmpty())
{
isSNMPInclNetOK=false;
m_dialog->confineerror_message->setText(tr("Incomlete network specification."));
}
else
{
m_dialog->confineerror_message->setText(" ");
isSNMPInclNetOK=true;
}
}
nextButton->setEnabled(isSNMPInclNetOK && isSeedHostOK);
}
int DiscoveryDruid::monitorOperation()
{
QString buf;
bool fl;
if (fwbdebug) qDebug("monitorOperation bop=%p isRunning=%d",
bop,(bop!=NULL)?bop->isRunning():-1);
fl=false;
while( logger->ready() )
{
buf= logger->getLine().c_str();
if (buf.endsWith('\n'))
buf = buf.left(buf.length() - 1);
addToLog(buf);
/*if (fwbdebug) qDebug("monitorOperation appending the following buf: (1)");
if (fwbdebug) qDebug(buf.toAscii().constData());
if (fwbdebug) qDebug("----------------------------------------------");*/
fl=true;
}
if (fl)
{
return 1;
}
if (bop==NULL)
{
return 0; // BackgroundOp has been disconnected
}
if (bop->isRunning())
{
return 1;
}
// send signal "completed", argument is 0 if ok and -1 if error
FWException *ex=bop->get_latest_error();
if (ex)
{
buf= ex->toString().c_str();
if (buf.endsWith('\n'))
buf = buf.left(buf.length() - 1);
addToLog(buf);
/*if (fwbdebug) qDebug("monitorOperation appending the following buf: (2)");
if (fwbdebug) qDebug(buf.toAscii().constData());
if (fwbdebug) qDebug("----------------------------------------------");*/
// completed(-1); // this sends signal to another widget
} else
{
// completed(0); // this sends signal to another widget
}
return 0;
}
void DiscoveryDruid::checkHostName()
{
if (!HostName.isEmpty())
{
userIsTyping=false;
QHostInfo::lookupHost(HostName,
this, SLOT(dnsFinish(QHostInfo)));
}
}
void DiscoveryDruid::checkSNMPCommunity()
{
if (m_dialog->snmpcommunity->text().isEmpty())
{
m_dialog->snmpcommunity_message->setText(tr("Empty community string"));
setNextEnabled(currentPage(),false);
}
else
{
m_dialog->snmpcommunity_message->setText("");
setNextEnabled(currentPage(),true);
}
}
void DiscoveryDruid::changeTargetObject(const QString &buf)
{
QTreeWidgetItem* item=m_dialog->typeChangingList->topLevelItem(0);
while (item!=0)
{
if (item->isSelected())
{
Objects[item->text(0)].type=buf.toLatin1().constData();
item->setText(2,buf);
}
item=m_dialog->typeChangingList->topLevelItem(
m_dialog->typeChangingList->indexOfTopLevelItem(item)+1);
}
}
void DiscoveryDruid::selectAllLast()
{
m_dialog->typeChangingList->selectAll();
}
void DiscoveryDruid::unselectAllLast()
{
m_dialog->typeChangingList->selectAll();
}
void DiscoveryDruid::typeAddress()
{
changeTargetObject(IPv4::TYPENAME);
}
void DiscoveryDruid::typeHost()
{
changeTargetObject(Host::TYPENAME);
}
void DiscoveryDruid::typeFirewall()
{
changeTargetObject(Firewall::TYPENAME);
}
/*
* Guess OS from the sysDescr string returned by the host. Returned OS
* name is always lower case one word, such as "linux", "ios"
*
* Examples of sysDescr strings:
*
* IOS (tm) 3600 Software (C3620-IK9O3S-M), Version 12.2(13), RELEASE SOFTWARE (fc1)
* Linux guardian 2.4.20 #2 Wed Nov 17 11:49:43 CET 2004 mips
* Linux crash 2.6.24-22-server #1 SMP Mon Nov 24 20:06:28 UTC 2008 x86_64
* Apple AirPort - Apple Computer, 2006. All rights Reserved
* Cisco Secure FWSM Firewall Version 2.3(4)
* Cisco PIX Firewall Version 6.2(1)
* Cisco Adaptive Security Appliance Version 8.2(0)227
*/
QString DiscoveryDruid::guessOS(const string &sysDescr)
{
QStringList elements = QString(sysDescr.c_str()).split(" ");
QString first = elements[0].toLower();
if (first == "cisco")
{
if (elements[1].toLower() == "adaptive" &&
elements[2].toLower() == "security" &&
elements[3].toLower() == "appliance") return "pix";
if (elements[1].toLower() == "pix") return "pix";
if (elements[1].toLower() == "secure" &&
elements[2].toLower() == "fwsm") return "pix";
}
if (first == "darwin") return "macosx";
if (first == "apple") return "macosx";
return first;
}
FWObject* DiscoveryDruid::addInterface(FWObject *parent, InterfaceData *in,
bool skip_ip_address_check)
{
ObjectManipulator *om = mw->activeProject()->m_panel->om;
if (!m_dialog->snmpincludeunnumbered->isChecked() && !skip_ip_address_check)
{
if (in->addr_mask.size()==0) return NULL;
if (in->addr_mask.front()->getAddressPtr()->isAny())
return NULL;
}
QString obj_name = in->name.c_str();
Interface *itf = NULL;
itf = Interface::cast(
mw->createObject(parent,
QString(Interface::TYPENAME), obj_name));
QString iname = om->getStandardName(itf, physAddress::TYPENAME, "mac");
iname = om->makeNameUnique(itf, iname, physAddress::TYPENAME);
physAddress *paddr = physAddress::cast(
mw->createObject(itf, physAddress::TYPENAME, iname)
);
paddr->setPhysAddress(in->mac_addr);
itf->setLabel(in->label);
itf->setSecurityLevel(in->securityLevel);
if (fwbdebug)
qDebug() << "Interface=" << obj_name
<< "type=" << in->interface_type.c_str();
if (!in->interface_type.empty())
{
itf->getOptionsObject()->setStr("type", in->interface_type);
if (in->interface_type == "8021q")
itf->getOptionsObject()->setInt("vlan_id", in->vlan_id);
} else
{
std::auto_ptr<interfaceProperties> int_prop(
interfacePropertiesObjectFactory::getInterfacePropertiesObject(parent));
if (int_prop->looksLikeVlanInterface(obj_name))
{
QString base_name;
int vlan_id;
int_prop->parseVlan(obj_name, &base_name, &vlan_id);
itf->getOptionsObject()->setStr("type", "8021q");
itf->getOptionsObject()->setInt("vlan_id", vlan_id);
}
}
if (in->addr_mask.size()==0 ||
in->addr_mask.front()->getAddressPtr()->isAny())
{
itf->setUnnumbered(true);
} else
{
list<InetAddrMask*>::iterator n;
for (n=in->addr_mask.begin(); n!=in->addr_mask.end(); ++n)
{
const InetAddr *addr = (*n)->getAddressPtr();
const InetAddr *netm = (*n)->getNetmaskPtr();
if (addr->isV4())
{
try
{
QString iname = om->getStandardName(itf, IPv4::TYPENAME, "ip");
iname = om->makeNameUnique(itf, iname, IPv4::TYPENAME);
IPv4 *ipv4= IPv4::cast(
om->createObject(itf, IPv4::TYPENAME, iname)
);
ipv4->setAddress(*addr);
ipv4->setNetmask(*netm);
} catch (FWException &ex)
{
cerr << "FWException: " << ex.toString() << endl;
}
}
if (addr->isV6())
{
try
{
QString iname = om->getStandardName(itf, IPv6::TYPENAME, "ip");
iname = om->makeNameUnique(itf, iname, IPv6::TYPENAME);
IPv6 *ipv6 = IPv6::cast(
om->createObject(itf, IPv6::TYPENAME, iname)
);
ipv6->setAddress(*addr);
ipv6->setNetmask(*netm);
} catch (FWException &ex)
{
cerr << "FWException: " << ex.toString() << endl;
}
}
}
}
return itf;
}
void DiscoveryDruid::createRealObjects()
{
ObjectDescriptor od;
string type, name, a;
int t=0;
m_dialog->lastprogress->setValue(0);
m_dialog->lastprogress->setMaximum( Objects.size());
QMap<QString,ObjectDescriptor >::iterator i;
for (i=Networks.begin(); i!=Networks.end(); ++i)
{
od=i.value();
if (od.isSelected)
{
type = od.type; // Network or NetworkIPv6
name = od.sysname;
a = od.addr.toString().c_str();
Address *net = Address::cast(
mw->createObject(type.c_str(), name.c_str()));
assert(net!=NULL);
net->setName(name);
net->setAddress(od.addr);
net->setNetmask(od.netmask);
mw->moveObject(m_dialog->libs->currentText(), net);
}
}
for (i=Objects.begin(); i!=Objects.end(); ++i)
{
od = i.value();
type = od.type;
name = od.sysname;
QString os = guessOS(od.descr);
a = od.addr.toString();
if (od.isSelected)
{
if (type==Host::TYPENAME || type==Firewall::TYPENAME)
{
FWObject *o=NULL;
o = mw->createObject(type.c_str(), name.c_str());
o->setName(name);
if (type==Firewall::TYPENAME)
{
if (os == "linux")
{
o->setStr("platform", "iptables");
o->setStr("host_OS", "linux24");
}
if (os == "freebsd")
{
o->setStr("platform", "pf");
o->setStr("host_OS", "freebsd");
}
if (os == "openbsd")
{
o->setStr("platform", "pf");
o->setStr("host_OS", "openbsd");
}
if (os == "ios")
{
o->setStr("platform", "iosacl");
o->setStr("host_OS", "ios");
}
if (os == "pix" || os == "fwsm")
{
o->setStr("platform", "pix");
o->setStr("host_OS", "pix_os");
}
if (os == "apple")
{
o->setStr("platform", "ipfw");
o->setStr("host_OS", "macosx");
}
if (os == "solaris")
{
o->setStr("platform", "ipf");
o->setStr("host_OS", "solaris");
}
Resources::setDefaultTargetOptions( o->getStr("platform"),
Firewall::cast(o) );
Resources::setDefaultTargetOptions( o->getStr("host_OS"),
Firewall::cast(o) );
}
if (od.interfaces.size()==0)
{
Interface *itf= Interface::cast(
mw->createObject(o,Interface::TYPENAME,"nic1")
);
if (od.addr.isV4())
{
IPv4 *ipv4= IPv4::cast(
mw->createObject(itf, IPv4::TYPENAME, a.c_str())
);
ipv4->setAddress(od.addr);
ipv4->setNetmask(InetAddr());
}
if (od.addr.isV6())
{
IPv6 *ipv6 = IPv6::cast(
mw->createObject(itf, IPv6::TYPENAME, a.c_str())
);
ipv6->setAddress(od.addr);
ipv6->setNetmask(InetAddr());
}
} else
{
if (fwbdebug)
{
map<int,InterfaceData>::iterator i;
for (i=od.interfaces.begin(); i!=od.interfaces.end(); ++i)
{
InterfaceData *intf = &(i->second);
QString str("Discovered interface %1: %2");
qDebug() <<
str.arg(intf->name.c_str()).arg(intf->mac_addr.c_str());
}
}
list<InterfaceData*> interface_tree;
std::auto_ptr<interfaceProperties> int_prop(
interfacePropertiesObjectFactory::getInterfacePropertiesObject(o));
int_prop->rearrangeInterfaces(od.interfaces, interface_tree);
if (interface_tree.size() != od.interfaces.size())
{
// Some interfaces have been converted to subinterfaces
// Show warning
QMessageBox::warning(
this, "Firewall Builder",
tr(
"Some discovered interfaces have been rearranged in "
"fwbuilder objects and recreated as subinterfaces to "
"reflect VLANs, bonding and bridging configurations. "
"The algorithm used to guess correct relationship "
"between interfaces and subinterfaces is imperfect "
"because of the limited information provided by SNMP "
"daemon. Pelase review created objects to make sure "
"generated configuration is accurate. "
"\n"
"\n"
"The program expects MAC addresses of bonding, bridge "
"and vlan interfaces to be the same. It is especially "
"important to review and fix generated objects if you "
"use MAC address spoofing."
),
tr("&Continue"), 0, 0,
0 );
}
list<InterfaceData*>::iterator it;
for (it=interface_tree.begin(); it!=interface_tree.end(); ++it)
{
InterfaceData *in = *it;
// if this interface has subinterfaces, add even if it
// has no ip address (last arg)
FWObject *intf = addInterface(
o, in, in->subinterfaces.size()!=0);
if (intf == NULL) continue;
list<InterfaceData*>::iterator sit;
for (sit=in->subinterfaces.begin();
sit!=in->subinterfaces.end(); ++sit)
{
InterfaceData *subint = *sit;
addInterface(intf, subint, true);
}
}
}
if (!od.descr.empty())
{
FWOptions* opt=(dynamic_cast<Host*>(o))->getOptionsObject();
opt->setStr("snmp_description",od.descr);
opt->setStr("snmp_location", od.location);
opt->setStr("snmp_contact", od.contact);
}
mw->moveObject(m_dialog->libs->currentText(), o);
} else if (type==Network::TYPENAME)
{
Network *net=dynamic_cast<Network*>(
mw->createObject(type.c_str(),name.c_str())
);
assert(net!=NULL);
net->setName(name);
net->setAddress(InetAddr(a));
net->setNetmask(InetAddr(InetAddr(a)));
mw->moveObject(m_dialog->libs->currentText(), net);
} else if (type==IPv4::TYPENAME)
{
IPv4 *obj=dynamic_cast<IPv4*>(
mw->createObject(type.c_str(),name.c_str())
);
assert(obj!=NULL);
obj->setName(name);
obj->setAddress(InetAddr(a));
obj->setNetmask(InetAddr(InetAddr::getAllOnes()));
mw->moveObject(m_dialog->libs->currentText(), obj);
}
}
m_dialog->lastprogress->setValue(t++);
qApp->processEvents();
}
m_dialog->lastprogress->setValue(Objects.size());
ProjectPanel *pp = mw->activeProject();
QString filename = pp->getFileName();
QCoreApplication::postEvent(mw, new reloadObjectTreeEvent(filename));
}
void DiscoveryDruid::importPlatformChanged(int cp)
{
if (fwbdebug)
qDebug("DiscoveryDruid::importPlatformChanged(): %d",cp);
switch (cp)
{
case 0:
m_dialog->import_text->setText(
QObject::tr("Firewall Builder can import Cisco IOS access lists "
"from the router configuration saved using 'show run' "
"or any other command that saves running config. The name "
"of the created firewall object, all of its interfaces "
"and their addresses will be configured automatically if "
"this information can be found in the configuration file."
)
);
break;
case 1:
m_dialog->import_text->setText(
QObject::tr("Firewall Builder can import iptables rules "
"from a file in iptables-save format. Firewall "
"name and addresses of its interfaces need "
"to be configured manually because iptables-save "
"file does not have this information. "
)
);
break;
}
}
//----------------------------------------------------------------------
ObjectDescriptor::ObjectDescriptor() {}
ObjectDescriptor::ObjectDescriptor(const ObjectDescriptor& od) {
have_snmpd = od.have_snmpd;
descr = od.descr;
contact = od.contact;
location = od.location;
sysname = od.sysname;
interfaces = od.interfaces;
MAC_addr = od.MAC_addr;
dns_info.name = od.dns_info.name;
dns_info.aliases = od.dns_info.aliases;
addr = od.addr;
type = od.type;
isSelected = od.isSelected;
netmask = od.netmask;
}
#ifdef HAVE_LIBSNMP
ObjectDescriptor::ObjectDescriptor(const libfwbuilder::CrawlerFind& cf) {
have_snmpd = cf.have_snmpd;
descr = cf.descr;
contact = cf.contact;
location = cf.location;
sysname = cf.sysname;
interfaces = cf.interfaces;
MAC_addr = cf.found_phys_addr;
dns_info.name = cf.name;
dns_info.aliases = cf.aliases;
}
#endif
ObjectDescriptor::~ObjectDescriptor() {};
ObjectDescriptor& ObjectDescriptor::operator=(const ObjectDescriptor& od) {
have_snmpd = od.have_snmpd;
descr = od.descr;
contact = od.contact;
location = od.location;
sysname = od.sysname;
interfaces = od.interfaces;
MAC_addr = od.MAC_addr;
dns_info.name = od.dns_info.name;
dns_info.aliases = od.dns_info.aliases;
addr = od.addr;
type = od.type;
isSelected = od.isSelected;
netmask = od.netmask;
return *this;
}
// ================================================================
WorkerThread::WorkerThread() : QThread()
{
Log = new QueueLogger();
}
WorkerThread::~WorkerThread()
{
delete Log;
}
void WorkerThread::setProgress(int p)
{
ProgressEvent *event = new ProgressEvent();
event->value=p;
QApplication::postEvent(Widget,event);
}
void WorkerThread::done()
{
DoneEvent *event=new DoneEvent();
QApplication::postEvent(Widget,event);
}
QString WorkerThread::getError()
{
return last_error;
}
void WorkerThread::run()
{
done();
}
// ================================================================
HostsFileImport::HostsFileImport(const QString &f) :
WorkerThread()
{
file_name = f;
}
void HostsFileImport::run()
{
*Log << "Discovery method: "
<< "Read file in hosts format. \n";
map<InetAddr, vector<string> > reverse_hosts;
HostsFile *hf;
/*
* read hosts file here
*/
hf=new HostsFile();
last_error="";
setProgress(10);
*Log << "Parsing file: " << file_name.toLatin1().constData() << "\n";
if (!file_name.isEmpty())
{
try
{
hf->parse( file_name.toAscii().constData() );
} catch ( FWException &ex )
{
last_error = ex.toString().c_str();
*Log << "Exception: " << last_error.toAscii().constData() << "\n";
delete hf;
done();
return;
}
reverse_hosts=hf->getAll();
delete hf;
setProgress(50);
*Log << "Loading the list ...\n";
/*
* convert map format
*/
hosts.clear();
map<InetAddr,vector<string> >::iterator i;
int count=reverse_hosts.size();
int t=0;
for (i=reverse_hosts.begin(); i!=reverse_hosts.end(); ++i)
{
ObjectDescriptor od;
od.addr = (*i).first;
od.sysname = ((*i).second).front();
hosts.push_back( od );
setProgress(50+(t++)*50/count);
}
}
*Log << "done.\n";
setProgress(100);
done();
}
// ================================================================
ConfigImport::ConfigImport(string *b, const std::string &p, const std::string &fwname) : WorkerThread()
{
buffer = b;
platform = p;
this->fwname = fwname;
}
ConfigImport::~ConfigImport()
{
if (imp) delete imp;
if (buffer) delete buffer;
}
void ConfigImport::run()
{
*Log << "Discovery method: Import firewall configuration.\n";
std::istringstream instream(*buffer);
imp = NULL;
if (platform == "iosacl") imp = new IOSImporter(mw->getCurrentLib(),
instream,
Log, fwname);
if (platform == "iptables") imp = new IPTImporter(mw->getCurrentLib(),
instream,
Log, fwname);
if (platform == "pix") imp = new PIXImporter(mw->getCurrentLib(),
instream,
Log, fwname);
// add other platforms here when available
if (imp)
{
try
{
imp->run();
} catch(ImporterException &e)
{
last_error = e.toString().c_str();
*Log << e.toString() << "\n";
}
} else
{
*Log << "Can not import configuration for choosen platform\n";
}
done();
}
void DiscoveryDruid::objNameChanged(QString)
{
m_dialog->nextButton->setEnabled(!(m_dialog->obj_name->text().isEmpty()
|| m_dialog->import_filename->text().isEmpty()));
m_dialog->nextButton->setDefault(true);
}