summaryrefslogtreecommitdiffstats
path: root/kmyfirewall/core/iptchain.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kmyfirewall/core/iptchain.cpp')
-rw-r--r--kmyfirewall/core/iptchain.cpp561
1 files changed, 561 insertions, 0 deletions
diff --git a/kmyfirewall/core/iptchain.cpp b/kmyfirewall/core/iptchain.cpp
new file mode 100644
index 0000000..9a9d2b1
--- /dev/null
+++ b/kmyfirewall/core/iptchain.cpp
@@ -0,0 +1,561 @@
+/***************************************************************************
+ begin : Mon Jan 28 2002
+ copyright : (C) 2002 by Christian Hubinger
+ email : chubinger@irrsinnig.org
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 "qptrlist.h"
+#include "qstring.h"
+#include "qmessagebox.h"
+
+// kde includes
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+//my includes
+#include "kmfdoc.h"
+#include "iptchain.h"
+#include "iptrule.h"
+#include "iptable.h"
+#include "kmferror.h"
+#include "xmlnames.h"
+
+namespace KMF {
+
+IPTChain::IPTChain( IPTable* table, const char* name, const QString& chainName, bool buildin ) : NetfilterObject( table, name ) {
+ // kdDebug() << "IPTChain::IPTChain(const QString& name,IPTable* table,bool buildin)" << endl;
+ m_err = new KMFError();
+
+ // m_object_type = NetfilterObject::CHAIN;
+ setName( chainName );
+ setTable( table );
+ is_build_in_chain = false;
+ has_default_target = false;
+ setBuildIn( buildin );
+ enable_log = false;
+
+
+ m_ruleset.setAutoDelete( false );
+
+ m_cmd_default_target = XML::Undefined_Value;
+ m_cmd_chain_definition = XML::Undefined_Value;
+ m_log_limit = XML::Undefined_Value;
+ m_log_prefix = XML::Undefined_Value;
+ m_log_burst = XML::Undefined_Value;
+ setUsed( true );
+}
+
+IPTChain::~IPTChain() {
+ kdDebug() << "\n\nIPChain::~IPTChain() : " << name() << endl;
+ m_ruleset.setAutoDelete( true );
+ m_ruleset.clear();
+ m_ruleset.setAutoDelete( false );
+ delete m_err;
+}
+
+int IPTChain::type() {
+// kdDebug() << "IPTChain::type()" << endl;
+ return NetfilterObject::CHAIN;
+}
+
+void IPTChain::clear() {
+ m_ruleset.setAutoDelete( true );
+ m_ruleset.clear();
+ m_ruleset.setAutoDelete( false );
+}
+
+void IPTChain::reset() {
+ m_ruleset.setAutoDelete( true );
+ m_ruleset.clear();
+ m_ruleset.setAutoDelete( false );
+ changed();
+}
+
+void IPTChain::setDefaultTarget( const QString& target ) {
+ // kdDebug() << "void IPTChain::setDefaultTarget(const QString& target) " << endl;
+ m_default_target = target;
+ has_default_target = true;
+ changed();
+}
+
+void IPTChain::setTable( IPTable* table ) {
+ setParent( table );
+ m_table = table;
+}
+
+IPTable* IPTChain::table() const {
+ return m_table;
+}
+
+QPtrList<IPTRule>& IPTChain::chainRuleset() const {
+ QPtrList<IPTRule>* ret_list = new QPtrList<IPTRule>;
+ *ret_list = m_ruleset;
+ return *ret_list;
+}
+
+void IPTChain::setBuildIn( bool build_in ) {
+ is_build_in_chain = build_in;
+ if ( is_build_in_chain ) {
+ const QString target = "DROP";
+ setDefaultTarget( target );
+ hasCustomDefaultTarget( false );
+ }
+}
+
+void IPTChain::hasCustomDefaultTarget( bool has ) {
+ if ( is_build_in_chain )
+ has_default_target = true;
+ else
+ has_default_target = has;
+ changed();
+}
+
+void IPTChain::setUsed( bool valid ) {
+ is_used = valid;
+ changed();
+}
+
+int IPTChain::indexOf( const IPTRule& rule ) {
+// kdDebug() << "int IPTChain::indexOf( IPTRule* " << rule.name() << " ) " << endl;
+ return m_ruleset.find( &rule );
+}
+
+IPTRule* IPTChain::addRule( const QString& rule_name, KMFError *err, int index ) {
+ kdDebug() << "IPTRule* IPTChain::addRule(QString& " << rule_name << ", KMFError *err) " << endl;
+
+ QString target = "DROP";
+ const QString& new_name = rule_name;
+ QString name = new_name;
+
+ for ( uint i = 0; i < m_ruleset.count(); i++ ) {
+ QString tmp_name = m_ruleset.at( i ) ->name();
+ if ( tmp_name == name ) {
+ err->setErrType(KMFError::NORMAL);
+ err->setErrMsg( i18n( "<qt><p>Unable to add rule: <b>%1</b> into chain: <b>%2</b>.<br>There is already a rule defined with that name. Please try again with another name (must be unique in that chain).</p></qt>" ).arg( tmp_name ).arg( NetfilterObject::name() ) );
+ return 0;
+ }
+ }
+
+ IPTRule* new_rule = new IPTRule( this, new_name.latin1(), new_name, target );
+ if ( ! new_rule ) {
+ err->setErrType(KMFError::FATAL);
+ err->setErrMsg( i18n("Sorry, a bad internal error occurred. This is a bug ;-(") );
+ return 0;
+ }
+ err->setErrType(KMFError::OK);
+ if ( index == -1 ) {
+ kdDebug() << "IPTChain::addRule: appending rule" << endl;
+ m_ruleset.append( new_rule );
+ } else {
+ if ( index < 0 || index > (int) chainRuleset().count() - -1 ) {
+ err->setErrType(KMFError::FATAL);
+ err->setErrMsg( i18n("Cannot insert rule at %1 This is a bug ;-(").arg( index ) );
+ return 0;
+ }
+ kdDebug() << "IPTChain::addRule: inserting rule at: " << index << endl;
+ m_ruleset.insert( index, new_rule );
+ }
+// regenerateRuleNumbers();
+ changed();
+ return new_rule;
+}
+
+
+KMFError* IPTChain::delRule( IPTRule* rule ) {
+ kdDebug() << "KMFError* IPTChain::delRule( IPTRule* rule )" << endl;
+ if ( m_ruleset.count() < 1 )
+ return false;
+
+ QString name = rule->name();
+ if ( m_ruleset.find( rule ) != -1 ) {
+ m_err->setErrType(KMFError::OK );
+ if ( ! m_ruleset.remove( rule ) ) {
+ rule->deleteLater();
+ rule = 0;
+ m_err->setErrType( KMFError::FATAL );
+ const QString& msg = i18n( "Sorry, can't find Rule: %1 in the Ruleset of this chain." ).arg( rule->name() );
+ m_err->setErrMsg( msg );
+ return m_err;
+ }
+ rule->deleteLater();
+ changed();
+ kdDebug() << "DONE." << endl;
+ return m_err;
+ } else {
+ m_err->setErrType( KMFError::FATAL );
+ const QString& msg = i18n( "Sorry, can't find Rule: %1 in the Ruleset of this chain." ).arg( rule->name() );
+ m_err->setErrMsg( msg );
+ return m_err;
+ }
+ kdDebug() << "Sorry can't delete Rule: " << rule->name() << ".\nRule not found in Chain !!!" << endl;
+ return m_err;
+}
+
+bool IPTChain::moveRule( IPTRule* rule, int how_much ) {
+ // kdDebug() << "void IPTChain::moveRule(IPTRule* rule,int how_much)" << endl;
+ int num = m_ruleset.find( rule );
+ int new_pos = num + how_much;
+ if ( new_pos < 0 || new_pos > ( int ) m_ruleset.count() - 1 ) {
+ // kdDebug() << "New Position is not Valid: " << new_pos << endl;
+ return false;
+ } else {
+ // kdDebug() << "Moving rule to position: " << new_pos << endl;
+ IPTRule *tmp_rule = m_ruleset.take( num );
+ m_ruleset.insert( new_pos, tmp_rule );
+ // regenerateRuleNumbers();
+ changed();
+ return true;
+ }
+}
+
+void IPTChain::setDropLogging( bool enabled, QString& limit, QString& burst, QString& prefix ) {
+ enable_log = enabled;
+
+ if ( !limit.isEmpty() )
+ m_log_limit = limit;
+ else
+ m_log_limit = "";
+ if ( !prefix.isEmpty() )
+ m_log_prefix = prefix;
+ else
+ m_log_prefix = "";
+ if ( !burst.isEmpty() )
+ m_log_burst = burst;
+ else
+ m_log_burst = XML::Undefined_Value;
+ changed();
+}
+
+
+QPtrList<IPTRule>& IPTChain::chainFwds() {
+ // kdDebug() << "QPtrList<IPTRule> IPTChain::chainFwds()" << endl;
+ QPtrList<IPTRule>* fwds = new QPtrList<IPTRule>;
+ QPtrListIterator<IPTRule> it( m_ruleset );
+ IPTRule* rule = 0;
+ while ( it.current() ) {
+ rule = it.current();
+ ++it;
+ QString target = rule->target();
+ // FIXME: lots of targets missing !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ if ( !target.isEmpty() && target != "ACCEPT" && target != "DROP" && target != "LOG"
+ && target != "REJECT" && target != "RETURN" && target != "DNAT" && target != "SNAT"
+ && target != "QUEUE" && target != "MIRROR" && target != "REDIRECT" && target != "MASQUERADE" ) {
+ //kdDebug() << "Found Forward to chain: " << target << endl;
+ fwds->append( rule );
+ }
+ }
+// kdDebug() << "EXIT: QPtrList<IPTRule>& IPTChain::chainFwds()" << endl;
+ return *fwds;
+}
+
+QPtrList<IPTRule>& IPTChain::chainFeeds() {
+// kdDebug() << "QPtrList<IPTRule> IPTChain::chainFeeds()" << endl;
+ QPtrList<IPTRule>* feeds = new QPtrList<IPTRule>;
+ IPTChain* tmp_chain;
+ QPtrList<IPTChain> table_chains = table() ->chains();
+ QPtrListIterator<IPTChain> it( table_chains );
+ while ( it.current() ) {
+ tmp_chain = it.current();
+ ++it;
+ // kdDebug() << "Searching in chain: " << tmp_chain->name() << endl;
+ if ( !tmp_chain->chainRuleset().isEmpty() ) {
+ IPTRule * tmp_rule;
+ QPtrList<IPTRule> rules = tmp_chain->chainRuleset();
+ QPtrListIterator<IPTRule> it2( rules );
+ while ( it2.current() ) {
+ tmp_rule = it2.current();
+ ++it2;
+ QString target = tmp_rule->target();
+ //kdDebug() << "Found Rule: " << tmp_rule->name() << " with target: " << target << endl;
+ if ( target == name() ) {
+ feeds->append( tmp_rule );
+ //kdDebug() << "Found feed: " << tmp_rule->name() << " from chain: " << tmp_chain->name() << endl;
+ }
+ }
+ }
+ }
+ // kdDebug() << "EXIT: QPtrList<IPTRule>& IPTChain::chainFeeds()" << endl;
+ return *feeds;
+}
+
+IPTRule* IPTChain::ruleForName( const QString& name ) {
+ IPTRule * tmp_rule = 0;
+ for ( tmp_rule = m_ruleset.first();tmp_rule; tmp_rule = m_ruleset.next() ) {
+ if ( tmp_rule->name() == name ) {
+ return tmp_rule;
+ }
+ }
+ return 0;
+}
+
+IPTRule* IPTChain::ruleForUuid( const QUuid& id ) {
+ IPTRule * tmp_rule = 0;
+ for ( tmp_rule = m_ruleset.first();tmp_rule; tmp_rule = m_ruleset.next() ) {
+ if ( tmp_rule->uuid() == id ) {
+ return tmp_rule;
+ }
+ }
+ return 0;
+
+}
+
+QString IPTChain::createIPTablesChainDefinition() {
+ QString chainDef = "";
+ if ( is_build_in_chain ) {
+ return chainDef;
+ } else {
+ m_cmd_chain_definition = "$IPT -t ";
+ m_cmd_chain_definition.append( m_table->name() );
+ m_cmd_chain_definition.append( " -N " );
+ m_cmd_chain_definition.append( name() );
+ return m_cmd_chain_definition;
+ }
+}
+
+QString IPTChain::createIPTablesChainDefaultTarget() {
+ // kdDebug() << "IPTChain::createIPTablesChainDefaultTarget()" << endl;
+ m_cmd_default_target = "$IPT -t ";
+ m_cmd_default_target.append( m_table->name() );
+ if ( is_build_in_chain ) {
+ m_cmd_default_target.append( " -P " );
+ m_cmd_default_target.append( name() );
+ m_cmd_default_target.append( " " );
+ } else {
+ m_cmd_default_target.append( " -A " );
+ m_cmd_default_target.append( name() );
+ m_cmd_default_target.append( " -j " );
+ }
+ m_cmd_default_target.append( m_default_target );
+ //kdDebug() << "Default Target Cmd: " << m_cmd_default_target << endl;
+ return m_cmd_default_target;
+}
+
+const QDomDocument& IPTChain::getDOMTree() {
+ // kdDebug() << "const QString& IPTChain::getIDOMree( )" << endl;
+ QDomDocument doc;
+ QDomElement root = doc.createElement( XML::Chain_Element );
+ NetfilterObject::saveUuid( root );
+
+
+ root.setAttribute( XML::Name_Attribute, name() );
+ if ( hasDefaultTarget() )
+ root.setAttribute( XML::DefaultTarget_Attribute, m_default_target );
+
+ root.setAttribute( XML::Description_Attribute, description() );
+
+ if ( isBuildIn() ) {
+ root.setAttribute( XML::BuiltIn_Attribute, XML::Yes_Value );
+ } else {
+ root.setAttribute( XML::BuiltIn_Attribute, XML::No_Value );
+ }
+
+ if ( logging() ) {
+ QDomElement logging = doc.createElement( XML::Logging_Element );
+ root.appendChild( logging );
+ logging.setAttribute( XML::Prefix_Attribute, m_log_prefix );
+ logging.setAttribute( XML::Limit_Attribute, m_log_limit );
+ logging.setAttribute( XML::Burst_Attribute, m_log_burst );
+ }
+
+ QPtrListIterator<IPTRule> it ( m_ruleset );
+ IPTRule *rule = 0;
+ while ( ( rule = it.current() ) != 0 ) {
+ ++it;
+ if ( rule) {
+ root.appendChild( rule->getDOMTree( ) );
+ // kdDebug() << "Got XML for Rule: " << rule->name() << endl;
+ } else {
+ kdDebug() << "Rule == 0"<< endl;
+ }
+ }
+ doc.appendChild( root );
+ return *( new QDomDocument( doc ) );
+}
+
+void IPTChain::loadXML( const QDomDocument& doc, QStringList& errors ) {
+ kdDebug() << "void IPTChain::loadXML( const QDomDocument& )" << endl;
+ QDomElement root = doc.documentElement();
+ loadXML( root, errors );
+}
+void IPTChain::loadXML( QDomNode root, QStringList& errors ) {
+/*
+void IPTChain::loadXML( const QDomDocument& doc ) {*/
+ kdDebug() << "\nvoid IPTChain::loadXML( const QDomDocument& doc )" << endl;
+ NetfilterObject::loadUuid( root, errors );
+ // QDomNode curr = root.toElement();
+
+ QString target = "";
+ QString builtin = "";
+ QString desc = "";
+ kdDebug() << "Parsing node: " << root.nodeName() << endl;
+ builtin = root.toElement().attribute( XML::BuiltIn_Attribute );
+ if ( !builtin.isEmpty() && builtin == XML::Yes_Value ) {
+ setBuildIn( true );
+ } else if ( !builtin.isEmpty() && builtin == XML::No_Value ) {
+ setBuildIn( false );
+ }
+
+ target = root.toElement().attribute( XML::DefaultTarget_Attribute );
+ if ( !target.isEmpty() ) {
+ if ( ! isBuildIn() )
+ hasCustomDefaultTarget( true );
+ setDefaultTarget( *(new QString( target ) ) );
+ }
+
+
+ desc = root.toElement().attribute( XML::Description_Attribute );
+ setDescription( *(new QString( desc ) ) );
+ kdDebug() << "Loading chain description: " << desc << endl;
+
+ kdDebug() << "Loading Chain: " << name() << endl;
+ kdDebug() << "Is built in: " << builtin << endl;
+ kdDebug() << "Description chain description: " << desc << endl;
+
+ QDomNode curr = root.firstChild();
+ QPtrList<IPTRule> used_rules;
+ while ( !curr.isNull() ) {
+ kdDebug() << "Parsing Node: " << curr.nodeName() << endl;
+ if ( curr.isElement() && curr.nodeName() == XML::Rule_Element ) {
+ QString name = curr.toElement().attribute( XML::Name_Attribute );
+ QString id = curr.toElement().attribute( XML::Uuid_Attribute );
+ QUuid rule_id( id );
+
+ // kdDebug() << "IPTChain: Start Parsing Rule: " << name << endl;
+ QDomDocument rule_xml;
+ rule_xml.appendChild( curr.cloneNode(true) );
+ IPTRule* rule = 0;
+ rule = ruleForUuid( rule_id );
+ if ( ! rule ) {
+ rule = ruleForName( name );
+ if ( ! rule ) {
+ rule = addRule( name, m_err );
+ if ( ! rule || m_err->errNum() != 0 ) {
+ kdDebug() << "ERROR: Couldn't create Rule: " << name << endl;
+ kdDebug() << "Error Message: " << m_err->errMsg() << endl;
+ return;
+ }
+ }
+ // kdDebug() << "IPTChain: Created Rule: " << name << endl;
+ }
+ rule->loadXML( rule_xml, errors );
+ used_rules.append( rule );
+ // kdDebug() << "IPTChain: Finished Parsing Rule: " << name << endl;
+ } else if( curr.isElement() && curr.nodeName() == XML::Logging_Element ) {
+ QString log_limit = "";
+ QString log_burst = "";
+ QString log_prefix = "";
+
+ enable_log = true;
+ log_limit = curr.toElement().attribute( XML::Limit_Attribute );
+ if( ! log_limit.isEmpty() )
+ m_log_limit = log_limit;
+
+ log_burst = curr.toElement().attribute( XML::Burst_Attribute );
+ if( ! log_burst.isEmpty() )
+ m_log_burst = log_burst;
+
+ log_prefix = curr.toElement().attribute( XML::Prefix_Attribute );
+ if( ! log_prefix.isEmpty() )
+ m_log_prefix = log_prefix;
+ }
+ curr = curr.nextSibling();
+ }
+
+
+ QPtrListIterator<IPTRule> it ( m_ruleset );
+ while ( it.current() ) {
+ // kdDebug() << "IPTChain::xloadXML() cleanup loop." << endl;
+ IPTRule *rule = it.current();
+ QPtrListIterator<IPTRule> it2 ( used_rules );
+ bool found = false;
+ while ( it2.current() ) {
+ IPTRule *rule2 = it2.current();
+ ++it2;
+ if ( rule2 == rule )
+ found = true;
+ }
+ if ( ! found ) {
+ m_err = delRule( rule );
+ if ( m_err->errNum() != 0 )
+ ++it;
+ } else {
+ ++it;
+ }
+ }
+ changed();
+}
+
+QPtrList<QStringList>& IPTChain::createIPTablesChainRules() {
+ // kdDebug() << "QPtrList<QStringList>& IPTChain::createIPTablesChainRules()" << endl;
+ QPtrList<QStringList>* all_rules = new QPtrList<QStringList>;
+ if ( !m_ruleset.isEmpty() ) {
+ //kdDebug() << "------- Chain Rules --------"<< endl;
+ IPTRule * rule;
+ for ( rule = m_ruleset.first(); rule; rule = m_ruleset.next() ) {
+ QString rule_name = rule->name();
+ QString rule_cmd = rule->toString();
+ QStringList* chainDefs = new QStringList();
+ chainDefs->append( rule_name );
+ if ( rule->enabled() ) {
+ chainDefs->append( rule_cmd );
+ } else {
+ QString warning = "if [ \"$verbose\" = \"1\" ]; then\n"
+ " echo \"Skipping Disabled Rule " + rule_name + "!!!\"\n"
+ "fi\n true";
+ chainDefs->append( warning );
+ }
+ all_rules->append( chainDefs );
+ }
+ }
+ if ( enable_log ) {
+ //kdDebug() << "------- Chain Logging --------"<< endl;
+ QString chain_log = "";
+ chain_log.append( "$IPT -t " );
+ chain_log.append( m_table->name() );
+ chain_log.append( " -A " );
+ chain_log.append( name() );
+ if ( ! m_log_limit.isEmpty() && m_log_limit != XML::Undefined_Value ) {
+ chain_log.append( " -m limit --limit " );
+ chain_log.append( m_log_limit );
+ if ( ! m_log_burst.isEmpty() && m_log_burst != XML::Undefined_Value ) {
+ chain_log.append( " --limit-burst " );
+ chain_log.append( m_log_burst );
+ }
+ }
+ chain_log.append( " -j LOG" );
+ if ( !m_log_prefix.isEmpty() && m_log_prefix != XML::Undefined_Value ) {
+ chain_log.append( " --log-prefix \"" );
+ chain_log.append( m_log_prefix );
+ chain_log.append( "\"" );
+ }
+ kdDebug() << chain_log << endl;
+ QStringList* chainDefs = new QStringList();
+ QString rule_name = i18n( "Chain: %1 Drop Logging" ).arg( name() );
+ chainDefs->append( rule_name );
+ chainDefs->append( chain_log );
+ all_rules->append( chainDefs );
+ }
+ //kdDebug() << "------- Chain Default Target --------"<< endl;
+ if ( has_default_target && !m_cmd_default_target.isEmpty() ) {
+ QString deftg = createIPTablesChainDefaultTarget();
+ QStringList* chainDefs = new QStringList();
+ QString rule_name = i18n( "Chain: %1 Default Target" ).arg( name() );
+ chainDefs->append( rule_name );
+ chainDefs->append( deftg );
+ all_rules->append( chainDefs );
+ }
+ // kdDebug() << "Leaving IPTChain::createIPTablesChainRules()" << endl;
+ return *all_rules;
+}
+
+}
+