You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kmyfirewall/kmyfirewall/core/kmfgenericdoc.cpp

564 lines
19 KiB

//
//
// C++ Implementation: $MODULE$
//
// Description:
//
//
// Author: Christian Hubinger <chubinger@irrsinnig.org>, (C) 2003
//
// Copyright: See COPYING file that comes with this distribution
//
//
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "kmfgenericdoc.h"
// QT includes
#include <tqfile.h>
#include <tqdom.h>
#include <tqstring.h>
#include <tqstringlist.h>
// KDE includes
#include <kapplication.h>
#include <kdebug.h>
#include <kstandarddirs.h>
#include <klocale.h>
#include <kio/netaccess.h>
#include <kio/job.h>
#include <ktrader.h>
#include <klibloader.h>
// Project includes
#include "../version.h"
#include "kmfcompilerinterface.h"
#include "kmfplugin.h"
#include "kmfpluginfactory.h"
#include "kmferror.h"
#include "kmfprotocol.h"
#include "kmfnetzone.h"
#include "kmfnetwork.h"
#include "kmfconfig.h"
#include "ipaddress.h"
#include "kmftarget.h"
#include "xmlnames.h"
namespace KMF {
KMFGenericDoc::KMFGenericDoc( NetfilterObject* parent, const char* name, KMFTarget* target ) : KMFDoc( parent, name ), KMFRulesetDoc( target ) {
kdDebug() << "KMFGenericDoc::KMFGenericDoc( TQObject *parent, const char *name ) : KMFDoc( parent, name )" << endl;
m_zones.setAutoDelete( false );
m_zone_incoming = 0;
m_zone_outgoing = 0;
m_zone_trusted= 0 ;
m_zone_malicious= 0 ;
m_zone_badClients= 0 ;
m_zone_badServers= 0 ;
m_allowIncomingConnections = false;
m_restrictOutgoingConnections = false;
m_allowPingReply = true;
m_limitPingReply = true;
m_useNat = false;
m_useMasquerade = false;
m_logDropped = true;
m_limitLog = true;
m_logPrefix = "KMF: ";
m_natAddress = new IPAddress(0,0,0,0);
m_outgoingInterface = XML::BoolOff_Value;
initDoc();
}
int KMFGenericDoc::type() {
// kdDebug() << "IPTRule::type()" << endl;
return NetfilterObject::GENERIC_RULESET;
}
KMFGenericDoc::~KMFGenericDoc() {}
void KMFGenericDoc::clear() {
kdDebug() << "void KMFGenericDoc::clear()" << endl;
m_zone_incoming->clear();
m_zone_outgoing->clear();
m_zone_trusted->clear();
m_zone_malicious->clear();
m_zone_badClients->clear();
m_zone_badServers->clear();
m_allowIncomingConnections = false;
m_restrictOutgoingConnections = false;
m_allowPingReply = true;
m_limitPingReply = true;
m_useNat = false;
m_useMasquerade = false;
m_logDropped = true;
m_limitLog = true;
m_logPrefix = "KMF: ";
m_natAddress->setAddress( 0, 0, 0, 0 );
m_outgoingInterface = XML::BoolOff_Value;
resetUrl();
setDescription( i18n("No description available") );
}
void KMFGenericDoc::initDoc() {
kdDebug() << "void KMFGenericDoc::initDoc()" << endl;
m_err = new KMFError;
m_url.setFileName( i18n( "Untitled" ) );
m_zone_incoming = new KMFNetZone( this, "incoming_world", "incoming_world" );
m_zone_outgoing = new KMFNetZone( this, "outgoing_world", "outgoing_world" );
m_zone_trusted= new KMFNetZone( this, "trusted_hosts", "trusted_hosts" );
m_zone_malicious= new KMFNetZone( this, "malicious_hosts", "malicious_hosts" );
m_zone_badClients= new KMFNetZone( this, "badClients_hosts", "badClients_hosts" );
m_zone_badServers= new KMFNetZone( this, "badServers_hosts", "badServers_hosts" );
m_zone_incoming->setGuiName( i18n( "Incoming Connections" ) );
m_zone_outgoing->setGuiName( i18n( "Outgoing Connections" ) );
m_zone_trusted->setGuiName( i18n( "Trusted Hosts" ) );
m_zone_malicious->setGuiName( i18n( "Malicious Hosts" ) );
m_zone_badClients->setGuiName( i18n( "Forbidden Clients" ) );
m_zone_badServers->setGuiName( i18n( "Forbidden Servers" ) );
m_zone_incoming->setZone( IPAddress( 0, 0, 0, 0 ), 0 );
m_zone_outgoing->setZone( IPAddress( 0, 0, 0, 0 ), 0 );
m_zone_trusted->setZone( IPAddress( 0, 0, 0, 0 ), 0 );
m_zone_malicious->setZone( IPAddress( 0, 0, 0, 0 ), 0 );
m_zone_badClients->setZone( IPAddress( 0, 0, 0, 0 ),0 );
m_zone_badServers->setZone( IPAddress( 0, 0, 0, 0 ), 0 );
m_zone_incoming->setDescription( i18n( "This is the global zone that contains\n"
"all valid IP addresses." ) );
m_zone_outgoing->setDescription( i18n( "This is the global zone that contains\n"
"all valid IP addresses." ) );
m_zone_trusted->setDescription( i18n( "Traffic coming from and going to hosts\n"
"will be accepted always.\n"
"Only add really trusted Hosts to this Zone" ) );
m_zone_malicious->setDescription( i18n("Traffic coming from and going to hosts\n"
"will be dropped always." ) );
m_zone_badClients->setDescription( i18n( "Hosts in this zone will not be able\n"
"to use services your computer provides." ) );
m_zone_badServers->setDescription( i18n( "You will not be able to use the services\n"
"of the hosts in that list." ) );
}
const TQString& KMFGenericDoc::getFileDialogFilter() {
return *( new TQString("*.kmfgrs|KMyFirewall Generic Ruleset(*.kmfgrs)") );
}
void KMFGenericDoc::setRestrictOutgoingConnections( bool onoff ) {
m_restrictOutgoingConnections = onoff;
}
void KMFGenericDoc::setAllowIncomingConnections( bool onoff ) {
m_allowIncomingConnections = onoff;
}
void KMFGenericDoc::setLogDropped( bool onoff ) {
m_logDropped = onoff;
}
void KMFGenericDoc::setLimitLog( bool onoff ) {
m_limitLog = onoff;
}
void KMFGenericDoc::setLogPrefix( const TQString& pre ) {
if ( ! pre.isNull() )
m_logPrefix = pre;
else
m_logPrefix = "";
}
bool KMFGenericDoc::isEmpty() {
// kdDebug() << "bool KMFGenericDoc::isEmpty()" << endl;
return false;
}
void KMFGenericDoc::setAllowPingReply( bool onoff ) {
m_allowPingReply = onoff;
}
void KMFGenericDoc::setLimitPingReply( bool onoff ){
m_limitPingReply = onoff;
}
void KMFGenericDoc::setUseNat( bool onoff ) {
m_useNat = onoff;
}
void KMFGenericDoc::setUseMasquerade( bool onoff ) {
m_useMasquerade = onoff;
}
void KMFGenericDoc::setNatAddress( const TQString& addr ) {
m_natAddress->setAddress( addr );
}
void KMFGenericDoc::setOutgoingInterface( const TQString& str ) {
m_outgoingInterface = str;
}
TQPtrList<KMFNetZone>& KMFGenericDoc::zones() const {
TQPtrList<KMFNetZone>* ret_val = new TQPtrList<KMFNetZone>;
*ret_val = m_zones;
return *ret_val;
}
KMFNetZone* KMFGenericDoc::addZone( const TQString& name, KMFError* err ) {
// kdDebug() << "KMFNetZone* addZone( const TQString& name, KMFError* err )" << endl;
bool found = false;
TQPtrListIterator<KMFNetZone> it ( m_zones );
while ( it.current() && ! found ) {
KMFNetZone * zone = it.current();
++it;
if ( zone->name() == name )
found = true;
}
if ( found ) {
err->setErrType( KMFError::NORMAL );
err->setErrMsg( i18n( "<qt>Sorry, cannot create Zone with name '<b>%1</b>':<br>"
"there already exists a zone with that name. Please try again"
" with another name that is unique within your configuration.</qt>" ).arg(name) );
return 0;
}
KMFNetZone * new_zone = new KMFNetZone( this, name.latin1(), name );
m_zones.append( new_zone );
err->setErrType( KMFError::OK );
return new_zone;
}
KMFError* KMFGenericDoc::delZone( KMFNetZone* zone ) {
// kdDebug() << "KMFError* delZone( const TQString& name )" << endl;
bool found = false;
TQPtrListIterator<KMFNetZone> it ( m_zones );
while ( it.current() && ! found ) {
KMFNetZone * z = it.current();
++it;
if ( zone == z ) {
found = true;
m_zones.remove( zone );
m_err->setErrType( KMFError::OK );
changed();
}
}
if ( ! found ) {
m_err->setErrType( KMFError::NORMAL );
m_err->setErrMsg( i18n( "<qt>Sorry, cannot create Zone with name: <b>%1</b>.<br>"
"There already exists a zone with that name; please try again"
" with another name that is unique within your configuration.</qt>" ).arg( zone->name() ) );
}
return m_err;
}
KMFNetZone* KMFGenericDoc::findZone( const TQString& name ) const {
// kdDebug() << "KMFNetZone* KMFGenericDoc::findZone( const TQString& name ) const" << endl;
TQPtrListIterator<KMFNetZone> it ( m_zones );
while ( it.current() ) {
KMFNetZone *z = it.current();
++it;
if ( z->name() == name )
return z;
}
return 0;
}
const TQString& KMFGenericDoc::compile() {
// kdDebug() << "const TQString& KMFGenericDoc::compile()" << endl;
KMFCompilerInterface* compiler = target()->compiler();
if ( ! compiler ) {
return *( new TQString("ERROR") );
}
return compiler->compile( this );
}
void KMFGenericDoc::parseDocument( const KURL& url, TQStringList& errors ) {
// kdDebug() << "KMFDoc* KMFGenericDoc::parseDocument( const KURL& )" << endl;
TQString xmlfile;
if ( ! KIO::NetAccess::download( url, xmlfile, KApplication::kApplication()->mainWidget() ) ) {
clear();
m_url.setFileName( i18n( "Untitled" ) );
return;
// return this;
}
if ( !xmlfile.isEmpty() ) {
// kdDebug() << "Found xmlfile: " << xmlfile << endl;
// delete old chainsets if there
clear();
TQFile kmfrsFile( xmlfile );
TQDomDocument domTree;
if ( !kmfrsFile.open( IO_ReadOnly ) ) {
return;
// return 0;
}
if ( !domTree.setContent( &kmfrsFile ) ) {
kmfrsFile.close();
return;
// return 0;
}
kmfrsFile.close();
kdDebug() << "############ Start Parsing ############" << endl;
loadXML( domTree, errors );
kdDebug() << "########## Finished Parsing ###########" << endl;
m_url = url;
// setUrl( url );
emit documentChanged();
KIO::NetAccess::removeTempFile( xmlfile );
return;
// return this;
}
KIO::NetAccess::removeTempFile( xmlfile );
// return this;
}
const TQDomDocument& KMFGenericDoc::getDOMTree() {
// kdDebug() << "const TQDomDocument& KMFGenericDoc::getDOMTree()" << endl;
TQDomDocument doc( "kmyfirewall-ruleset" );
TQDomElement root = doc.createElement( XML::GenericDoc_DocumentElement );
NetfilterObject::saveUuid( root );
root.setAttribute( XML::Version_Attribute, KMYFIREWALL_VERSION );
root.setAttribute( XML::MinVersion_Attribute, "1.0.0" );
root.setAttribute( XML::MaxVersion_Attribute, "~" );
root.appendChild( m_zone_incoming->getDOMTree() );
root.appendChild( m_zone_outgoing->getDOMTree() );
root.appendChild( m_zone_badClients->getDOMTree() );
root.appendChild( m_zone_badServers->getDOMTree() );
root.appendChild( m_zone_malicious->getDOMTree() );
root.appendChild( m_zone_trusted->getDOMTree() );
TQDomElement abstract = doc.createElement( XML::Abstract_Element );
if ( restrictOutgoingConnections() )
abstract.setAttribute( XML::RestrictOutgoingConnections_Attribute ,XML::BoolOn_Value );
else
abstract.setAttribute( XML::RestrictOutgoingConnections_Attribute ,XML::BoolOff_Value );
if ( allowIncomingConnections() )
abstract.setAttribute( XML::AllowIncomingConnections_Attribute ,XML::BoolOn_Value );
else
abstract.setAttribute( XML::AllowIncomingConnections_Attribute ,XML::BoolOff_Value );
abstract.setAttribute( XML::Description_Attribute, description() );
abstract.setAttribute( XML::Name_Attribute, name() );
root.appendChild( abstract );
TQDomElement logging = doc.createElement( XML::Logging_Element );
if ( logDropped() )
logging.setAttribute( XML::LogDropped_Attribute, XML::BoolOn_Value );
else
logging.setAttribute( XML::LogDropped_Attribute, XML::BoolOff_Value );
if ( limitLog() )
logging.setAttribute( XML::LimitLog_Attribute, XML::BoolOn_Value );
else
logging.setAttribute( XML::LimitLog_Attribute, XML::BoolOff_Value );
logging.setAttribute( XML::LogPrefix_Attribute, logPrefix() );
root.appendChild( logging );
TQDomElement icmp = doc.createElement( XML::ICMP_Element );
if ( allowPingReply() ) {
icmp.setAttribute( XML::AllowPingReply_Attribute, XML::BoolOn_Value );
} else {
icmp.setAttribute( XML::AllowPingReply_Attribute, XML::BoolOff_Value );
}
if ( limitPingReply() )
icmp.setAttribute( XML::LimitPingReply_Attribute, XML::BoolOn_Value );
else
icmp.setAttribute( XML::LimitPingReply_Attribute, XML::BoolOff_Value );
root.appendChild( icmp );
TQDomElement nat = doc.createElement( XML::NAT_Element );
if ( useNat() )
nat.setAttribute( XML::UseNat_Attribute, XML::BoolOn_Value );
else
nat.setAttribute( XML::UseNat_Attribute, XML::BoolOff_Value );
if ( useMasquerade() )
nat.setAttribute( XML::UseMasquerade_Attribute, XML::BoolOn_Value );
else
nat.setAttribute( XML::UseMasquerade_Attribute, XML::BoolOff_Value );
nat.setAttribute( XML::NatAddress_Attribute, m_natAddress->toString() );
TQString allowedIn = "";
nat.setAttribute( XML::OutgoingInterface_Attribute, m_outgoingInterface );
root.appendChild( nat );
doc.appendChild( root );
return *( new TQDomDocument( doc ) );
}
void KMFGenericDoc::loadXML( const TQDomDocument& doc, TQStringList& errors ) {
kdDebug() << "void KMFGenericDoc::loadXML( const TQDomDocument& )" << endl;
TQDomElement root = doc.documentElement();
if ( root.nodeName() != XML::GenericDoc_DocumentElement ) {
kdDebug() << "!!! ERROR: Wrong XML format " << root.nodeName() << " found !!!" << endl;
errors.append( KMFError::getAsString( KMFError::FATAL, i18n("Wrong XML format <b>%1</b> found! Expected kmfgrs").arg( root.nodeName() ) ) );
return;
}
loadXML( root, errors );
}
void KMFGenericDoc::loadXML( TQDomNode root, TQStringList& errors ) {
// void KMFGenericDoc::loadXML( const TQDomDocument& doc ) {
// kdDebug() << "void KMFGenericDoc::loadXML( const TQDomDocument& )" << endl;
// TQDomElement root = doc.documentElement();
NetfilterObject::loadUuid ( root, errors );
TQDomNode curr = root.firstChild();
while ( !curr.isNull() ) {
kdDebug() << "Parsing Node: " << curr.nodeName() << endl;
if ( curr.isElement() && curr.nodeName() == XML::NetZone_Element ) {
TQString name = "";
name = curr.toElement().attribute( XML::Name_Attribute );
TQDomDocument zone_doc;
zone_doc.appendChild( curr.cloneNode(true) );
if ( name == "incoming_world" ) {
// kdDebug() << "\nKMFIPTDoc: Start Parsing INCOMMING ZONES" << endl;
m_zone_incoming->loadXML( zone_doc, errors );
// kdDebug() << "KMFIPTDoc: Finished Parsing INCOMMING ZONES" << endl;
}
if ( name == "outgoing_world" ) {
// kdDebug() << "\nKMFIPTDoc: Start Parsing OUTGOING ZONES" << endl;
m_zone_outgoing->loadXML( zone_doc, errors );
// kdDebug() << "KMFIPTDoc: Finished Parsing OUTGOING ZONES" << endl;
}
if ( name == "trusted_hosts" ) {
// kdDebug() << "\nKMFIPTDoc: Start Parsing TRUSTED HOSTS" << endl;
m_zone_trusted->loadXML( zone_doc, errors );
// kdDebug() << "KMFIPTDoc: Finished Parsing TRUSTED HOSTS" << endl;
}
if ( name == "malicious_hosts" ) {
// kdDebug() << "\nKMFIPTDoc: Start Parsing MALICIOUS HOSTS" << endl;
m_zone_malicious->loadXML( zone_doc, errors );
// kdDebug() << "KMFIPTDoc: Finished Parsing MALICIOUS HOSTS" << endl;
}
if ( name == "badClients_hosts" ) {
// kdDebug() << "\nKMFIPTDoc: Start Parsing BADCLIENTS HOSTS" << endl;
m_zone_badClients->loadXML( zone_doc, errors );
// kdDebug() << "KMFIPTDoc: Finished Parsing BADCLIENTS HOSTS" << endl;
}
if ( name == "badServers_hosts" ) {
// kdDebug() << "\nKMFIPTDoc: Start Parsing BADSERVERS HOSTS" << endl;
m_zone_badServers->loadXML( zone_doc, errors );
// kdDebug() << "KMFIPTDoc: Finished Parsing BADSERVERS HOSTS" << endl;
}
} else if ( curr.isElement() && curr.nodeName() == XML::Logging_Element ) {
// kdDebug() << "\nKMFIPTDoc: Start Parsing Logging" << endl;
TQString logDropped = "";
TQString limitLog = "";
TQString logPrefix = "";
logDropped = curr.toElement().attribute( XML::LogDropped_Attribute );
limitLog = curr.toElement().attribute( XML::LimitLog_Attribute );
logPrefix = curr.toElement().attribute( XML::LogPrefix_Attribute );
if ( logDropped == XML::BoolOn_Value )
setLogDropped( true );
else
setLogDropped( false );
if ( limitLog == XML::BoolOn_Value )
setLimitLog( true );
else
setLimitLog( false );
setLogPrefix( logPrefix );
// kdDebug() << "KMFIPTDoc: Finished Parsing Logging" << endl;
} else if ( curr.isElement() && curr.nodeName() == XML::ICMP_Element ) {
// kdDebug() << "\nKMFIPTDoc: Start Parsing ICMP" << endl;
TQString allowPing = "";
TQString limitPing = "";
allowPing = curr.toElement().attribute( XML::AllowPingReply_Attribute );
limitPing = curr.toElement().attribute( XML::LimitPingReply_Attribute );
if ( allowPing == XML::BoolOn_Value)
setAllowPingReply( true );
else
setAllowPingReply( false );
if ( limitPing == XML::BoolOn_Value )
setLimitPingReply( true );
else
setLimitPingReply( false );
// kdDebug() << "KMFIPTDoc: Finished Parsing ICMP" << endl;
} else if ( curr.isElement() && curr.nodeName() == XML::NAT_Element ) {
// kdDebug() << "\nKMFIPTDoc: Start Parsing NAT" << endl;
TQString useNat = "";
TQString useMasquerade = "";
TQString natAddress = "";
TQString outgoingInterface = "";
useNat = curr.toElement().attribute( XML::UseNat_Attribute );
useMasquerade = curr.toElement().attribute( XML::UseMasquerade_Attribute );
natAddress = curr.toElement().attribute( XML::NatAddress_Attribute );
outgoingInterface = curr.toElement().attribute( XML::OutgoingInterface_Attribute );
if ( useNat == XML::BoolOn_Value)
setUseNat( true );
else
setUseNat( false );
if ( useMasquerade == XML::BoolOn_Value)
setUseMasquerade( true );
else
setUseMasquerade( false );
m_outgoingInterface = outgoingInterface;
m_natAddress->setAddress( natAddress );
// kdDebug() << "Stored NAT address: " << m_natAddress->toString() << endl;
// kdDebug() << "KMFIPTDoc: Finished Parsing NAT" << endl;
}else if ( curr.isElement() && curr.nodeName() == XML::Abstract_Element ) {
kdDebug() << "KMFIPTDoc: Start Parsing Abstract" << endl;
TQString allowIncomingConnections = "";
TQString restrictOutgoingConnections = "";
TQString description = "";
TQString name = "";
allowIncomingConnections =curr.toElement().attribute( XML::AllowIncomingConnections_Attribute );
restrictOutgoingConnections =curr.toElement().attribute( XML::RestrictOutgoingConnections_Attribute );
description += curr.toElement().attribute( XML::Description_Attribute );
if ( ! description.isNull() )
setDescription( *( new TQString( description ) ) );
name += curr.toElement().attribute( XML::Name_Attribute );
if ( ! name.isNull() )
setName( *( new TQString( name ) ) );
if ( allowIncomingConnections == XML::BoolOn_Value )
setAllowIncomingConnections( true );
else
setAllowIncomingConnections( false );
if ( restrictOutgoingConnections == XML::BoolOn_Value )
setRestrictOutgoingConnections( true );
else
setRestrictOutgoingConnections( false );
kdDebug() << "KMFIPTDoc: Finished Parsing Abstract" << endl;
}
curr = curr.nextSibling();
}
}
}