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.
463 lines
16 KiB
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"
|