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/compilers/pf/kmfpfcompiler.cpp

463 lines
16 KiB

//
// C++ Implementation: kmfpfcompiler
//
// Description:
//
//
// Author: Christian Hubinger <e9806056@student.tuwien.ac.at>, (C) 2004
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "kmfpfcompiler.h"
// TQt includes
#include <tqptrlist.h>
#include <tqstringlist.h>
#include <tqmultilineedit.h>
// KDE includes
#include <kdebug.h>
#include <tdelocale.h>
#include <tdeaboutdata.h>
#include <tdelocale.h>
// Project includes
#include "../../core/kmfgenericdoc.h"
#include "../../core/kmfiptdoc.h"
#include "../../core/kmfnetzone.h"
#include "../../core/kmfnethost.h"
#include "../../core/kmfprotocol.h"
#include "../../core/kmferror.cpp"
#include "../../core/kmfprotocol.h"
#include "../../core/kmfprotocolusage.h"
#include "../../kmfwidgets/kmflistview.h"
namespace KMF {
KMFPFCompiler::KMFPFCompiler( TQObject* parent, const char* name ) : KMFPlugin( parent, name ) {
m_osName = "openbsd";
m_osGUIName = "OpenBSD";
m_backendName = "pf";
m_backendGUIName = "PF";
if ( genericDoc() ) {
new TDEAction( i18n( "Export as &PF (OpenBSD) Script" ), "fileexport",
0, this, TQ_SLOT( slotExportPF() ), actionCollection(), "compile_pf" );
setXMLFile( "kmfpfcompiler.rc" );
kdDebug() << "KMFPFCompiler: Finished initialisation." << endl;
}
}
KMFPFCompiler::~KMFPFCompiler() {}
const TQString& KMFPFCompiler::osName(){
return m_osName;
}
const TQString& KMFPFCompiler::osGUIName(){
return m_osGUIName;
}
const TQString& KMFPFCompiler::backendName(){
return m_backendName;
}
const TQString& KMFPFCompiler::backendGUIName(){
return m_backendGUIName;
}
void KMFPFCompiler::compile() {
kdDebug() << "void KMFPFCompiler::compile()" << endl;
kdDebug() << "Doc XML:\n" << m_doc->getXMLSniplet() << endl;
}
void KMFPFCompiler::slotExportPF() {
kdDebug() << "KMFPFCompiler::slotExportIPT()" << endl;
TQString s = compile( genericDoc() );
kdDebug() << "Generated scrip: " << s << endl;
}
const TQString& KMFPFCompiler::compile( KMFGenericDoc* gendoc ) {
kdDebug() << "const TQString& KMFPFCompiler::compile( KMFGenericDoc* doc )" << endl;
if ( gendoc ) {
m_compiledScript = "";
setupNatRules( gendoc );
setupLocalhostRules();
setupInAndOutHosts( gendoc->trustedHostsZone(), "pass" );
setupInAndOutHosts( gendoc->maliciousHostsZone(), "block" );
setupForbiddenHosts( gendoc->badClientsHostsZone(), "in" );
setupForbiddenHosts( gendoc->badServersHostsZone(), "out" );
setupICMPRules( gendoc );
createIncommingACCESSRules( 0, gendoc );
createOutgoingACCESSRules( 0, gendoc );
setupPolicies( gendoc );
kdDebug() << "Return compiled pf:\n " << m_compiledScript << endl;
return m_compiledScript;
} else {
return *( new TQString( "ERROR: Couldn't compile document - may be wrong type " ) );
}
}
void KMFPFCompiler::setupInAndOutHosts( KMFNetZone* zone , const TQString& cmd ) {
kdDebug() << "KMFPFCompiler::setupInAndOutHosts( KMFNetZone* )" << endl;
if ( zone->hosts().count() == 0 ) {
return;
}
TQPtrListIterator<KMFTarget> it ( zone->hosts() );
if ( cmd == "pass" ) {
m_compiledScript.append( "\n# Trusted Hosts\n" );
} else {
m_compiledScript.append( "\n# Maliciuous Hosts\n" );
}
while ( it.current() ) {
KMFNetHost *host = dynamic_cast<KMFNetHost*> ( *it );
++it;
if ( cmd == "pass" ) {
m_compiledScript.append( "pass in quick from " );
m_compiledScript.append( host->address()->toString() );
m_compiledScript.append( " to any keep state\n" );
} else {
m_compiledScript.append( "block in quick from " );
m_compiledScript.append( host->address()->toString() );
m_compiledScript.append( " to any\n" );
}
}
}
void KMFPFCompiler::setupForbiddenHosts( KMFNetZone* zone, const TQString& inOut ) {
if ( zone->hosts().count() == 0 ) {
return;
}
TQPtrListIterator<KMFTarget> it ( zone->hosts() );
if ( inOut == "in" ) {
m_compiledScript.append( "\n# Forbidden Clients\n" );
} else {
m_compiledScript.append( "\n# Forbidden Server\n" );
}
while ( it.current() ) {
KMFNetHost *host = dynamic_cast<KMFNetHost*> ( *it );
++it;
if ( inOut == "in" ) {
m_compiledScript.append( "block in quick from " );
m_compiledScript.append( host->address()->toString() );
m_compiledScript.append( " to any\n" );
} else {
m_compiledScript.append( "block out quick from any to " );
m_compiledScript.append( host->address()->toString() );
m_compiledScript.append( "\n" );
}
}
}
void KMFPFCompiler::setupICMPRules( KMFGenericDoc* doc ) {
if ( ! doc->allowPingReply() ) {
return;
}
m_compiledScript.append( "\n# Allow ping\n" );
m_compiledScript.append( "pass in quick inet proto icmp all icmp-type { 0, 3, 11 } keep state\n" );
}
void KMFPFCompiler::setupLocalhostRules() {
m_compiledScript.append( "\n# Allow loopback traffic\n" );
m_compiledScript.append( "pass in quick on lo0 from 127.0.0.1 to 127.0.0.1 keep state\n" );
m_compiledScript.append( "pass out quick on lo0 from 127.0.0.1 to 127.0.0.1 keep state\n" );
}
void KMFPFCompiler::createIncommingACCESSRules( KMFNetZone* zone, KMFGenericDoc* doc ) {
kdDebug() << "void KMFPFCompiler::createIncommingACCESSRules( KMFNetZone* zone, KMFGenericDoc* doc )" << endl;
if ( ! doc->allowIncomingConnections() ) {
return;
}
if ( zone == 0 ) {
m_compiledScript.append( TQString("\n# Settup Inncomming Connection access rules\n") );
zone = doc->incomingZone();
}
TQPtrList<KMFNetZone>& children = zone->zones();
TQPtrListIterator<KMFNetZone> it( children );
while( it.current() ) {
createIncommingACCESSRules( it.current(), doc );
++it;
}
TQPtrList<KMFTarget>& zoneHosts = zone->hosts();
TQPtrListIterator<KMFTarget> itZoneHosts ( zoneHosts );
while ( itZoneHosts.current() ) {
KMFNetHost* host = dynamic_cast<KMFNetHost*> ( itZoneHosts.current() );
++itZoneHosts;
m_compiledScript.append( TQString("\n# Settup rules for host %1 [%2]\n").arg( host->guiName() ).arg( zone->address()->toString() ) );
TQPtrList<KMFProtocolUsage>& hostProts = host->protocols();
TQPtrListIterator<KMFProtocolUsage> itHostProtocols ( hostProts );
while ( itHostProtocols.current() ) {
KMFProtocolUsage* prot = itHostProtocols.current();
++itHostProtocols;
if ( ! host->protocolInherited( prot->protocol()->uuid() ) ) {
m_compiledScript.append( TQString("# Settup rules for protocol %1\n").arg( prot->protocol()->name() ) );
if ( prot->protocol()->tcpPorts().count() > 0 ) {
m_compiledScript.append( "pass in " );
if ( prot->logging() || host->logIncoming() ) {
m_compiledScript.append( " log " );
}
m_compiledScript.append( " quick inet proto tcp from " );
m_compiledScript.append( zone->address()->toString() );
m_compiledScript.append( "/32 " );
m_compiledScript.append( " to any " );
m_compiledScript.append( " port " );
m_compiledScript.append( getPortList( prot->protocol()->tcpPorts() ) );
m_compiledScript.append( " synproxy state\n" );
}
if ( prot->protocol()->udpPorts().count() > 0 ) {
m_compiledScript.append( "pass in " );
if ( prot->logging() || host->logIncoming() ) {
m_compiledScript.append( " log " );
}
m_compiledScript.append( " quick inet proto udp from " );
m_compiledScript.append( zone->address()->toString() );
m_compiledScript.append( "/32" );
m_compiledScript.append( " to any " );
m_compiledScript.append( " port " );
m_compiledScript.append( getPortList( prot->protocol()->udpPorts() ) );
m_compiledScript.append( " keep state\n" );
}
} else {
kdDebug() << "Skipping inherited Portocol: " << prot->protocol()->name() << " in zone: " << zone->guiName() << endl;
}
}
}
m_compiledScript.append( TQString("\n# Settup rules for zone %1 [%2/%3]\n").arg( zone->guiName() ).arg( zone->address()->toString() ).arg( zone->maskLength() ) );
TQPtrList<KMFProtocolUsage>& zoneProts = zone->protocols();
TQPtrListIterator<KMFProtocolUsage> itZoneProtocols ( zoneProts );
while ( itZoneProtocols.current() ) {
KMFProtocolUsage* prot = itZoneProtocols.current();
++itZoneProtocols;
if ( ! zone->protocolInherited( prot->protocol()->uuid() ) ) {
m_compiledScript.append( TQString("# Settup rules for protocol %1\n").arg( prot->protocol()->name() ) );
if ( prot->protocol()->tcpPorts().count() > 0 ) {
m_compiledScript.append( "pass in " );
if ( prot->logging() ) {
m_compiledScript.append( " log " );
}
m_compiledScript.append( " quick inet proto tcp from " );
m_compiledScript.append( zone->address()->toString() );
m_compiledScript.append( "/" );
m_compiledScript.append( TQString::number( zone->maskLength() ) );
m_compiledScript.append( " to any " );
m_compiledScript.append( " port " );
m_compiledScript.append( getPortList( prot->protocol()->tcpPorts() ) );
m_compiledScript.append( " synproxy state\n" );
}
if ( prot->protocol()->udpPorts().count() > 0 ) {
m_compiledScript.append( "pass in " );
if ( prot->logging() ) {
m_compiledScript.append( " log " );
}
m_compiledScript.append( " quick inet proto udp from " );
m_compiledScript.append( zone->address()->toString() );
m_compiledScript.append( "/" );
m_compiledScript.append( TQString::number( zone->maskLength() ) );
m_compiledScript.append( " to any " );
m_compiledScript.append( " port " );
m_compiledScript.append( getPortList( prot->protocol()->udpPorts() ) );
m_compiledScript.append( " keep state\n" );
}
} else {
kdDebug() << "Skipping inherited Portocol: " << prot->protocol()->name() << " in zone: " << zone->guiName() << endl;
}
}
}
void KMFPFCompiler::createOutgoingACCESSRules( KMFNetZone* zone, KMFGenericDoc* doc ) {
kdDebug() << "void KMFPFCompiler::createOutgoingACCESSRules( KMFNetZone* zone, KMFGenericDoc* doc )" << endl;
if ( ! doc->restrictOutgoingConnections() ) {
return;
}
if ( zone == 0 ) {
m_compiledScript.append( TQString("\n# Settup Outgoing Connection access rules\n") );
zone = doc->outgoingZone();
}
TQPtrList<KMFNetZone>& children = zone->zones();
TQPtrListIterator<KMFNetZone> it( children );
while( it.current() ) {
createIncommingACCESSRules( it.current(), doc );
++it;
}
TQPtrList<KMFTarget>& zoneHosts = zone->hosts();
TQPtrListIterator<KMFTarget> itZoneHosts ( zoneHosts );
while ( itZoneHosts.current() ) {
KMFNetHost* host = dynamic_cast<KMFNetHost*> ( itZoneHosts.current() );
++itZoneHosts;
m_compiledScript.append( TQString("\n# Settup rules for host %1 [%2]\n").arg( host->guiName() ).arg( zone->address()->toString() ) );
TQPtrList<KMFProtocolUsage>& hostProts = host->protocols();
TQPtrListIterator<KMFProtocolUsage> itHostProtocols ( hostProts );
while ( itHostProtocols.current() ) {
KMFProtocolUsage* prot = itHostProtocols.current();
++itHostProtocols;
if ( ! host->protocolInherited( prot->protocol()->uuid() ) ) {
m_compiledScript.append( TQString("# Settup rules for protocol %1\n").arg( prot->protocol()->name() ) );
if ( prot->protocol()->tcpPorts().count() > 0 ) {
m_compiledScript.append( "pass out " );
if ( prot->logging() || host->logIncoming() ) {
m_compiledScript.append( " log " );
}
m_compiledScript.append( " quick inet proto tcp from " );
m_compiledScript.append( zone->address()->toString() );
m_compiledScript.append( "/32 " );
m_compiledScript.append( " to any " );
m_compiledScript.append( " port " );
m_compiledScript.append( getPortList( prot->protocol()->tcpPorts() ) );
m_compiledScript.append( " synproxy state\n" );
}
if ( prot->protocol()->udpPorts().count() > 0 ) {
m_compiledScript.append( "pass out " );
if ( prot->logging() || host->logIncoming() ) {
m_compiledScript.append( " log " );
}
m_compiledScript.append( " quick inet proto udp from " );
m_compiledScript.append( zone->address()->toString() );
m_compiledScript.append( "/32" );
m_compiledScript.append( " to any " );
m_compiledScript.append( " port " );
m_compiledScript.append( getPortList( prot->protocol()->udpPorts() ) );
m_compiledScript.append( " keep state\n" );
}
} else {
kdDebug() << "Skipping inherited Portocol: " << prot->protocol()->name() << " in zone: " << zone->guiName() << endl;
}
}
}
m_compiledScript.append( TQString("\n# Settup rules for zone %1 [%2/%3]\n").arg( zone->guiName() ).arg( zone->address()->toString() ).arg( zone->maskLength() ) );
TQPtrList<KMFProtocolUsage>& zoneProts = zone->protocols();
TQPtrListIterator<KMFProtocolUsage> itZoneProtocols ( zoneProts );
while ( itZoneProtocols.current() ) {
KMFProtocolUsage* prot = itZoneProtocols.current();
++itZoneProtocols;
if ( ! zone->protocolInherited( prot->protocol()->uuid() ) ) {
m_compiledScript.append( TQString("# Settup rules for protocol %1\n").arg( prot->protocol()->name() ) );
if ( prot->protocol()->tcpPorts().count() > 0 ) {
m_compiledScript.append( "pass out " );
if ( prot->logging() ) {
m_compiledScript.append( " log " );
}
m_compiledScript.append( " quick inet proto tcp from " );
m_compiledScript.append( zone->address()->toString() );
m_compiledScript.append( "/" );
m_compiledScript.append( TQString::number( zone->maskLength() ) );
m_compiledScript.append( " to any " );
m_compiledScript.append( " port " );
m_compiledScript.append( getPortList( prot->protocol()->tcpPorts() ) );
m_compiledScript.append( " synproxy state\n" );
}
if ( prot->protocol()->udpPorts().count() > 0 ) {
m_compiledScript.append( "pass out " );
if ( prot->logging() ) {
m_compiledScript.append( " log " );
}
m_compiledScript.append( " quick inet proto udp from " );
m_compiledScript.append( zone->address()->toString() );
m_compiledScript.append( "/" );
m_compiledScript.append( TQString::number( zone->maskLength() ) );
m_compiledScript.append( " to any " );
m_compiledScript.append( " port " );
m_compiledScript.append( getPortList( prot->protocol()->udpPorts() ) );
m_compiledScript.append( " keep state\n" );
}
} else {
kdDebug() << "Skipping inherited Portocol: " << prot->protocol()->name() << " in zone: " << zone->guiName() << endl;
}
}
}
TQString KMFPFCompiler::getPortList( TQValueList<int>& list ) {
TQString ret = "{";
TQValueList<int>::iterator ports;
uint i = 0;
for( ports = list.begin(); ports != list.end(); ++ports ) {
ret.append( TQString::number( *ports ) );
if ( i != list.count() - 1 ) {
ret.append( ", " );
}
i++;
}
ret.append( "}" );
return ret;
}
void KMFPFCompiler::setupPolicies( KMFGenericDoc* doc ) {
m_compiledScript.append( "\n# Default action for unhandled packets\n" );
m_compiledScript.append( "block in quick\n" );
if ( doc->restrictOutgoingConnections() ) {
m_compiledScript.append( "block out quick\n" );
} else {
m_compiledScript.append( "pass out quick all keep state\n" );
}
}
void KMFPFCompiler::setupNatRules( KMFGenericDoc* doc ) {
if ( ! doc->useNat() ) {
return;
}
m_compiledScript.append( "\n# Setup NAT\n" );
if ( doc->useMasquerade() ) {
m_compiledScript.append( TQString("nat on %1 from any to any -> (%2)\n").arg( doc->outgoingInterface() ).arg( doc->outgoingInterface() ) );
} else {
m_compiledScript.append( TQString("nat on %1 from any to any -> %2\n").arg( doc->outgoingInterface() ).arg( doc->natAddress()->toString() ) );
}
}
// TDEInstance* KMFPFCompilerFactory::s_instance = 0L;
// TDEAboutData* KMFPFCompilerFactory::s_about = 0L;
KMFPFCompilerFactory::KMFPFCompilerFactory( TQObject* parent, const char* name )
: KLibFactory( parent, name ) {
// s_instance = new TDEInstance( "KMFPFCompilerFactory" );
}
TQObject* KMFPFCompilerFactory::createObject( TQObject* parent, const char* name,
const char*, const TQStringList & ) {
TQObject * obj = new KMFPFCompiler( parent, name );
emit objectCreated( obj );
return obj;
}
// TDEInstance* KMFPFCompilerFactory::instance() {
// if ( !s_instance ) {
// s_instance = new TDEInstance( "KMFPFCompilerFactory" );
// }
// return s_instance;
// }
extern "C" {
void* init_libkmfcompiler_pf() {
return new KMFPFCompilerFactory;
}
}
}
#include "kmfpfcompiler.moc"