// // C++ Implementation: kmfpfcompiler // // Description: // // // Author: Christian Hubinger , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #include "kmfpfcompiler.h" // TQt includes #include #include #include // KDE includes #include #include #include #include // 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 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 ( *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 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 ( *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& children = zone->zones(); TQPtrListIterator it( children ); while( it.current() ) { createIncommingACCESSRules( it.current(), doc ); ++it; } TQPtrList& zoneHosts = zone->hosts(); TQPtrListIterator itZoneHosts ( zoneHosts ); while ( itZoneHosts.current() ) { KMFNetHost* host = dynamic_cast ( itZoneHosts.current() ); ++itZoneHosts; m_compiledScript.append( TQString("\n# Settup rules for host %1 [%2]\n").arg( host->guiName() ).arg( zone->address()->toString() ) ); TQPtrList& hostProts = host->protocols(); TQPtrListIterator 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& zoneProts = zone->protocols(); TQPtrListIterator 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& children = zone->zones(); TQPtrListIterator it( children ); while( it.current() ) { createIncommingACCESSRules( it.current(), doc ); ++it; } TQPtrList& zoneHosts = zone->hosts(); TQPtrListIterator itZoneHosts ( zoneHosts ); while ( itZoneHosts.current() ) { KMFNetHost* host = dynamic_cast ( itZoneHosts.current() ); ++itZoneHosts; m_compiledScript.append( TQString("\n# Settup rules for host %1 [%2]\n").arg( host->guiName() ).arg( zone->address()->toString() ) ); TQPtrList& hostProts = host->protocols(); TQPtrListIterator 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& zoneProts = zone->protocols(); TQPtrListIterator 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& list ) { TQString ret = "{"; TQValueList::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"