diff options
Diffstat (limited to 'kmyfirewall/core/iptchain.cpp')
-rw-r--r-- | kmyfirewall/core/iptchain.cpp | 561 |
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; +} + +} + |