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.
548 lines
17 KiB
548 lines
17 KiB
/***************************************************************************
|
|
begin : Mon Feb 4 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. *
|
|
* *
|
|
***************************************************************************/
|
|
//project includes
|
|
#include "iptrule.h"
|
|
// #include "iptruleoption.h"
|
|
#include "iptchain.h"
|
|
#include "iptable.h"
|
|
#include "kmfdoc.h"
|
|
#include "kmferror.h"
|
|
#include "kmfcheckinput.h"
|
|
#include "xmlnames.h"
|
|
|
|
//TQt includes
|
|
#include "tqstring.h"
|
|
#include "tqdict.h"
|
|
|
|
// kde includes
|
|
#include <kdebug.h>
|
|
#include <tdelocale.h>
|
|
|
|
namespace KMF {
|
|
|
|
IPTRule::IPTRule( IPTChain* tmp_chain, const char *name, const TQString& tmp_name, const TQString& tmp_target ) : NetfilterObject( tmp_chain, name ) {
|
|
// m_object_type = NetfilterObject::RULE;
|
|
setName( XML::Undefined_Value );
|
|
m_target = XML::Undefined_Value;
|
|
m_check_input = new KMFCheckInput();
|
|
m_err = new KMFError();
|
|
setChain( tmp_chain );
|
|
setTable( tmp_chain->table() );
|
|
setName( tmp_name );
|
|
setTarget( tmp_target );
|
|
setCustomRule( false );
|
|
m_enabled = true;
|
|
m_log_rule = false;
|
|
m_options.setAutoDelete( false );
|
|
ipt_cmd = "$IPT";
|
|
tab = "-t";
|
|
ap = "-A";
|
|
ws = " ";
|
|
post = "-j";
|
|
}
|
|
|
|
IPTRule::~IPTRule() {
|
|
// kdDebug() << "\nIPTRule::~IPTRule()" << endl;
|
|
delete m_check_input;
|
|
delete m_err;
|
|
clear();
|
|
}
|
|
|
|
int IPTRule::type() {
|
|
// kdDebug() << "IPTRule::type()" << endl;
|
|
return NetfilterObject::RULE;
|
|
}
|
|
|
|
void IPTRule::clear() {
|
|
m_options.setAutoDelete( true );
|
|
m_options.clear();
|
|
m_options.setAutoDelete( false );
|
|
}
|
|
|
|
KMFError* IPTRule::setRuleName( const TQString& tmp_name ) {
|
|
kdDebug() << "IPTRule::setName( const TQString& tmp_name )" << endl;
|
|
TQString inp = tmp_name;
|
|
m_check_input->checkInput( inp, "RULENAME", m_err );
|
|
if ( m_err->errType() != KMFError::OK ) {
|
|
kdDebug() << "-- Name unchanged: invalid name" << tmp_name << endl;
|
|
return m_err;
|
|
}
|
|
NetfilterObject::setName( tmp_name );
|
|
changed();
|
|
return m_err;
|
|
}
|
|
|
|
void IPTRule::setChain( IPTChain* ch ) {
|
|
setParent( ch );
|
|
m_chain = ch;
|
|
changed();
|
|
}
|
|
|
|
void IPTRule::setTable( IPTable* tmp_table ) {
|
|
m_table = tmp_table;
|
|
changed();
|
|
// kdDebug() << "Rule Table: " << *m_table->name() << endl;
|
|
}
|
|
|
|
void IPTRule::setEnabled( bool on ) {
|
|
m_enabled = on;
|
|
changed();
|
|
}
|
|
|
|
void IPTRule::setLogging( bool on ) {
|
|
m_log_rule = on;
|
|
changed();
|
|
}
|
|
|
|
void IPTRule::setTarget( const TQString& tmp_target ) {
|
|
if ( !tmp_target.isNull() ) {
|
|
m_target = tmp_target;
|
|
}
|
|
|
|
TQPtrList<TQString>* available_options = IPTRuleOption::getAvailableOptionTypes();
|
|
for ( uint j = 0;j < available_options->count();j++ ) {
|
|
TQString type = *available_options->at( j );
|
|
IPTRuleOption* opt = 0;
|
|
opt = getOptionForName( type );
|
|
if ( opt && opt->isTargetOption() ) {
|
|
TQStringList args;
|
|
opt->loadValues( args );
|
|
}
|
|
}
|
|
changed();
|
|
}
|
|
|
|
void IPTRule::setCustomRule( bool on ) {
|
|
m_custom_rule = on;
|
|
changed();
|
|
}
|
|
|
|
int IPTRule::ruleNum() const {
|
|
return chain()->indexOf( *this );
|
|
//return m_rule_num;
|
|
}
|
|
|
|
const TQString& IPTRule::target() const {
|
|
return m_target;
|
|
}
|
|
|
|
bool IPTRule::isForward() const {
|
|
//FIXME: Is that sematically correct???
|
|
if ( m_target == "ACCEPT" || m_target == "DROP" ||
|
|
m_target == "LOG" || m_target == "QUEUE" ||
|
|
m_target == "RETURN" || m_target == "REJECT" ||
|
|
m_target == "MIRROR" || m_target == "SNAT" ||
|
|
m_target == "DNAT" || m_target == "REDIRECT" ||
|
|
m_target == "MASQUERADE" || m_target == "MARK" ||
|
|
m_target == "TOS" ) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
TQStringList IPTRule::availableTargets() const {
|
|
kdDebug() << "TQStringList availableTargets() const {" << endl;
|
|
TQStringList targets;
|
|
TQString table = chain() ->table() ->name();
|
|
TQString name = chain() ->name();
|
|
if ( table.isEmpty() || name.isEmpty() ) {
|
|
kdDebug() << "KMFRuleEdit::slotAddValidTargets( const IPTChain& chain ): ERROR: name or table not found in table" << endl;
|
|
return *( new TQStringList() );
|
|
}
|
|
// general Targets
|
|
targets << "ACCEPT" << "DROP" << "LOG" << "QUEUE" << "RETURN";
|
|
if ( name == Constants::InputChain_Name || name == Constants::OutputChain_Name || name == Constants::ForwardChain_Name )
|
|
targets << "REJECT";
|
|
|
|
if ( name == Constants::InputChain_Name || name == Constants::OutputChain_Name || name == Constants::PreRoutingChain_Name )
|
|
targets << "MIRROR";
|
|
|
|
if ( table == Constants::NatTable_Name && name == Constants::PostRoutingChain_Name )
|
|
targets << "SNAT";
|
|
|
|
if ( table == Constants::NatTable_Name && ( name == Constants::PreRoutingChain_Name || name == Constants::OutputChain_Name ) ) {
|
|
targets << "DNAT" << "REDIRECT";
|
|
}
|
|
|
|
if ( table == Constants::NatTable_Name && name == Constants::PostRoutingChain_Name )
|
|
targets << "MASQUERADE";
|
|
|
|
if ( table == Constants::MangleTable_Name ) {
|
|
targets << "MARK" << "TOS";
|
|
}
|
|
|
|
if ( table == Constants::FilterTable_Name || table == Constants::NatTable_Name || table == Constants::MangleTable_Name ) {
|
|
TQPtrList<IPTChain> tmp_chains = chain() ->table() ->chains();
|
|
TQPtrListIterator<IPTChain> it( tmp_chains );
|
|
while ( it.current() ) {
|
|
IPTChain * tmp_ch = it.current();
|
|
++it;
|
|
if ( !tmp_ch->isBuildIn() && tmp_ch->name() != name ) {
|
|
// kdDebug() << "Adding Chain: " << tmp_ch->name() << " to Targets. " << endl;
|
|
targets << tmp_ch->name();
|
|
}
|
|
}
|
|
}
|
|
return targets;
|
|
}
|
|
|
|
IPTRuleOption* IPTRule::getOptionForName( const TQString& type ) {
|
|
IPTRuleOption * option_obj;
|
|
option_obj = m_options.find( type );
|
|
if ( option_obj == 0 && !type.stripWhiteSpace().isEmpty() ) {
|
|
// kdDebug() << "Creating new IPTRuleOption( IPTRule* )" << endl;
|
|
option_obj = new IPTRuleOption( this, type.latin1() );
|
|
option_obj->setOptionType( type );
|
|
m_options.insert( type, option_obj );
|
|
return option_obj;
|
|
} else {
|
|
return option_obj;
|
|
}
|
|
}
|
|
|
|
bool IPTRule::addRuleOption( TQString& par_name, TQPtrList<TQString>& cmds ) {
|
|
//############# start new implementation ##################//
|
|
TQString new_par_name = "";
|
|
if ( par_name == "src_ip" || par_name == "dest_ip" ) {
|
|
// kdDebug() << "Translating to new option name: " << par_name << " -> ip_opt" << endl;
|
|
new_par_name = "ip_opt";
|
|
} else if ( par_name == "mac" ) {
|
|
// kdDebug() << "Translating to new option name: " << par_name << " -> mac_opt" << endl;
|
|
new_par_name = "mac_opt";
|
|
|
|
} else {
|
|
new_par_name = par_name;
|
|
}
|
|
if ( new_par_name.stripWhiteSpace().isEmpty() ) {
|
|
return false;
|
|
}
|
|
IPTRuleOption * option_obj;
|
|
option_obj = m_options.find( new_par_name );
|
|
if ( option_obj == 0 ) {
|
|
// kdDebug() << "Creating new IPTRuleOption( IPTRule* )" << endl;
|
|
option_obj = new IPTRuleOption( this, new_par_name.latin1() );
|
|
m_options.insert( new_par_name, option_obj );
|
|
} else {
|
|
// kdDebug() << "Option: " << new_par_name << "Allready in Dict" << endl;
|
|
}
|
|
kdDebug() << "+ Adding Opiton: " << new_par_name << endl;
|
|
option_obj->setOptionType( new_par_name );
|
|
if ( ! cmds.isEmpty() ) {
|
|
TQStringList args;
|
|
for ( uint i = 0; i < cmds.count(); i++ )
|
|
args << *( new TQString( *cmds.at( i ) ) );
|
|
option_obj->loadValues( args );
|
|
} else {
|
|
option_obj->reset();
|
|
}
|
|
// kdDebug() << "Rule->getXMLSniplet(): " << getXMLSniplet() << endl;
|
|
changed();
|
|
return true;
|
|
}
|
|
|
|
bool IPTRule::addTargetOption( TQString& par_name, TQPtrList<TQString>& cmds ) {
|
|
//############# start new implementation ##################//
|
|
TQString new_par_name = "";
|
|
new_par_name = par_name;
|
|
|
|
if ( new_par_name.stripWhiteSpace().isEmpty() ) {
|
|
return false;
|
|
}
|
|
|
|
IPTRuleOption * option_obj;
|
|
option_obj = m_options.find( new_par_name );
|
|
if ( option_obj == 0 ) {
|
|
// kdDebug() << "Creating new IPTRuleOption( IPTRule* )" << endl;
|
|
option_obj = new IPTRuleOption( this, par_name.latin1() );
|
|
m_options.insert( new_par_name, option_obj );
|
|
option_obj->setTargetOption( true );
|
|
} else {
|
|
// kdDebug() << "Option: " << new_par_name << "Allready in Dict" << endl;
|
|
option_obj->setTargetOption( true );
|
|
}
|
|
option_obj->setOptionType( new_par_name );
|
|
option_obj->setTargetOption( true );
|
|
if ( ! cmds.isEmpty() ) {
|
|
TQStringList args;
|
|
for ( uint i = 0; i < cmds.count(); i++ )
|
|
args << *( new TQString( *cmds.at( i ) ) );
|
|
option_obj->loadValues( args );
|
|
} else {
|
|
option_obj->reset();
|
|
}
|
|
// kdDebug() << "Rule->getXMLSniplet(): " << getXMLSniplet() << endl;
|
|
changed();
|
|
return true;
|
|
}
|
|
|
|
|
|
const TQString& IPTRule::toString() {
|
|
// kdDebug() << "\nconst TQString& IPTRule::toString()" << endl;
|
|
option_cmd = "";
|
|
option_cmd.append( ipt_cmd ); // $IPT
|
|
option_cmd.append( ws );
|
|
option_cmd.append( tab ); // -t
|
|
option_cmd.append( ws );
|
|
option_cmd.append( m_table->name() ); // <TABLE>
|
|
option_cmd.append( ws );
|
|
option_cmd.append( ap ); // -A
|
|
option_cmd.append( ws );
|
|
option_cmd.append( m_chain->name() ); // <CHAIN>
|
|
option_cmd.append( ws );
|
|
// append all normal rule options
|
|
TQPtrList<TQString>* known_types = 0;
|
|
known_types = IPTRuleOption::getAvailableOptionTypes();
|
|
if ( known_types == 0 ) {
|
|
kdDebug() << "ERROR: IPTRuleOption::getAvailableOptionTypes() == 0\n" << endl;
|
|
} else {
|
|
// kdDebug() << "Found Number of Types: " << known_types->count() << endl;
|
|
for ( uint i = 0; i < known_types->count(); i++ ) {
|
|
TQString* option_name = 0;
|
|
option_name = known_types->at( i );
|
|
if ( option_name == 0 ) {
|
|
kdDebug() << "ERROR: option_name == 0" << endl;
|
|
} else {
|
|
// kdDebug() << "Searching for Option: " << *option_name << endl;
|
|
IPTRuleOption* opt = 0;
|
|
opt = m_options.find( *option_name );
|
|
if ( opt && ! opt->isEmpty() && ! opt->isTargetOption() ) {
|
|
TQString option = opt->toString();
|
|
// kdDebug() << "Add Option: " << opt->toString() << endl;
|
|
if ( !option.isEmpty() ) {
|
|
option_cmd.append( opt->toString() );
|
|
option_cmd.append( ws );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
option_cmd. append( post );
|
|
option_cmd. append( ws );
|
|
option_cmd.simplifyWhiteSpace();
|
|
if ( logging() ) {
|
|
TQString new_line = option_cmd;
|
|
new_line. append( "LOG" );
|
|
new_line. append( " --log-prefix \"Rule " + name() + ": \"" );
|
|
new_line.simplifyWhiteSpace();
|
|
new_line.append( "\n" );
|
|
option_cmd.prepend( new_line );
|
|
}
|
|
|
|
option_cmd. append( m_target );
|
|
option_cmd. append( ws );
|
|
|
|
TQString target_options = "";
|
|
if ( known_types == 0 ) {
|
|
kdDebug() << "ERROR: IPTRuleOption::getAvailableOptionTypes() == 0\n" << endl;
|
|
} else {
|
|
// kdDebug() << "Found Number of Types: " << known_types->count() << endl;
|
|
for ( uint i = 0; i < known_types->count(); i++ ) {
|
|
TQString* option_name = 0;
|
|
option_name = known_types->at( i );
|
|
if ( option_name == 0 ) {
|
|
kdDebug() << "ERROR: option_name == 0" << endl;
|
|
} else {
|
|
// kdDebug() << "Searching for Option: " << *option_name << endl;
|
|
IPTRuleOption* opt = 0;
|
|
opt = m_options.find( *option_name );
|
|
if ( opt && opt->isTargetOption() && ! opt->isEmpty() ) {
|
|
// kdDebug() << "Add Option: " << opt->toString() << endl;
|
|
TQString option = "";
|
|
option = opt->toString();
|
|
if ( !option.isEmpty() ) {
|
|
target_options.append( opt->toString() );
|
|
target_options.append( ws );
|
|
target_options.simplifyWhiteSpace();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
option_cmd.append( target_options );
|
|
|
|
// kdDebug() << "Rule Cmd Line for Rule " << m_name << ": " << option_cmd << endl;
|
|
if ( ! logging() )
|
|
option_cmd.simplifyWhiteSpace();
|
|
return *( new TQString( option_cmd ) );
|
|
}
|
|
|
|
|
|
const TQDomDocument& IPTRule::getDOMTree( ) {
|
|
// kdDebug() << "const TQString& IPTRule::getDOMTree( )" << endl;
|
|
TQDomDocument doc;
|
|
TQDomElement root = doc.createElement( XML::Rule_Element );
|
|
NetfilterObject::saveUuid( root );
|
|
root.setAttribute( XML::Num_Attribute, ruleNum() );
|
|
root.setAttribute( XML::Name_Attribute, name() );
|
|
root.setAttribute( XML::Target_Attribute, m_target );
|
|
root.setAttribute( XML::Description_Attribute, description() );
|
|
if ( enabled() ) {
|
|
root.setAttribute( XML::Enabled_Attribute, XML::Yes_Value );
|
|
} else {
|
|
root.setAttribute( XML::Enabled_Attribute, XML::No_Value );
|
|
}
|
|
|
|
if ( customRule() ) {
|
|
root.setAttribute( XML::CustomRule_Attribute, XML::Yes_Value );
|
|
} else {
|
|
root.setAttribute( XML::CustomRule_Attribute, XML::No_Value );
|
|
}
|
|
|
|
if ( logging() ) {
|
|
root.setAttribute( XML::Logging_Attribute, XML::Yes_Value );
|
|
} else {
|
|
root.setAttribute( XML::Logging_Attribute, XML::No_Value );
|
|
}
|
|
|
|
TQPtrList<TQString>* available_options = 0;
|
|
available_options = IPTRuleOption::getAvailableOptionTypes();
|
|
if ( available_options ) {
|
|
TQPtrListIterator<TQString> it ( *available_options );
|
|
TQString *type = 0;
|
|
while ( ( type = it.current() ) != 0 ) {
|
|
++it;
|
|
if ( type ) {
|
|
IPTRuleOption * opt = 0;
|
|
opt = m_options.find( *type );
|
|
if ( opt ) {
|
|
root.appendChild( opt->getDOMTree( ) );
|
|
// kdDebug() << "Got XML for Rule Option Type: " << *type << endl;
|
|
} else {
|
|
// kdDebug() << "No option with type: " << *type << " found. " << endl;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
doc.appendChild( root );
|
|
return *( new TQDomDocument( doc ) );
|
|
}
|
|
|
|
void IPTRule::loadXML( const TQDomDocument& doc, TQStringList& errors ) {
|
|
kdDebug() << "void IPTRule::loadXML( const TQDomDocument& )" << endl;
|
|
TQDomElement root = doc.documentElement();
|
|
loadXML( root, errors );
|
|
}
|
|
void IPTRule::loadXML( TQDomNode root, TQStringList& errors ) {
|
|
// void IPTRule::loadXML( const TQDomDocument& doc ) {
|
|
// kdDebug() << "void IPTRule::loadXML( const TQDomDocument& doc )" << endl;
|
|
// kdDebug() << "Parsing XML:\n" << doc.toString() << endl;
|
|
// TQDomElement root = doc.documentElement();
|
|
NetfilterObject::loadUuid ( root, errors );
|
|
TQString name = "";
|
|
TQString num = "";
|
|
TQString logging = "";
|
|
TQString desc = "";
|
|
TQString target = "";
|
|
TQString custom = "";
|
|
TQString enabled = "";
|
|
name = root.toElement().attribute( XML::Name_Attribute );
|
|
num = root.toElement().attribute( XML::Num_Attribute );
|
|
logging = root.toElement().attribute( XML::Logging_Attribute );
|
|
custom = root.toElement().attribute( XML::CustomRule_Attribute );
|
|
target = root.toElement().attribute( XML::Target_Attribute );
|
|
desc = root.toElement().attribute( XML::Description_Attribute );
|
|
enabled = root.toElement().attribute( XML::Enabled_Attribute );
|
|
|
|
if ( logging == XML::Yes_Value ) {
|
|
setLogging( true );
|
|
} else {
|
|
setLogging( false );
|
|
}
|
|
if ( enabled == XML::Yes_Value ) {
|
|
setEnabled( true );
|
|
} else {
|
|
setEnabled( false );
|
|
}
|
|
|
|
if ( custom == XML::Yes_Value ) {
|
|
setCustomRule( true );
|
|
} else {
|
|
setCustomRule( false );
|
|
}
|
|
|
|
setTarget( *( new TQString( target ) ) );
|
|
setDescription( *( new TQString( desc ) ) );
|
|
setName( *( new TQString( name ) ) );
|
|
/* bool ok;
|
|
int rule_number = num.toInt( &ok );
|
|
if ( ok )
|
|
setRuleNum( rule_number );*/
|
|
TQPtrList<TQString> *avail_opts = IPTRuleOption::getAvailableOptionTypes();
|
|
TQPtrListIterator<TQString> it ( *avail_opts );
|
|
while ( it.current() ) {
|
|
TQString name = *it.current();
|
|
++it;
|
|
IPTRuleOption *opt = getOptionForName( name );
|
|
if ( opt )
|
|
opt->reset();
|
|
}
|
|
|
|
TQDomNode curr = root.firstChild();
|
|
while ( !curr.isNull() ) {
|
|
// kdDebug() << "IPTRule: Parsing Node: " << curr.nodeName() << endl;
|
|
if ( curr.isElement() && curr.nodeName() == XML::RuleOption_Element ) {
|
|
TQString type = curr.toElement().attribute( XML::Type_Attribute );
|
|
// kdDebug() << "IPTRule: Start Parsing Option: " << type << endl;
|
|
TQDomDocument opt_xml;
|
|
opt_xml.appendChild( curr.cloneNode( true ) );
|
|
IPTRuleOption* opt = 0;
|
|
opt = m_options.find( *( new TQString( type ) ) );
|
|
if ( opt == 0 ) {
|
|
TQPtrList<TQString> list;
|
|
list.append( new TQString( "" ) );
|
|
addRuleOption( type, list );
|
|
opt = m_options.find( *( new TQString( type ) ) );
|
|
if ( ! opt ) {
|
|
kdDebug() << "ERROR: Couldn't create Option: " << type << endl;
|
|
return ;
|
|
}
|
|
// kdDebug() << "IPTRule: Created Option: " << type << endl;
|
|
}
|
|
opt->loadXML( opt_xml, errors );
|
|
// kdDebug() << "IPTRule: Finished Parsing Option: " << type << endl;
|
|
}
|
|
curr = curr.nextSibling();
|
|
}
|
|
changed();
|
|
}
|
|
|
|
void IPTRule::createRuleClone( IPTRule* new_rule ) {
|
|
// kdDebug() << "IPTRule& IPTRule::createRuleClone()" << endl;
|
|
TQString na = name();
|
|
if ( na.length() > 15 ) {
|
|
na = na.left( 15 ) ;
|
|
}
|
|
new_rule->setCustomRule( m_custom_rule );
|
|
new_rule->setDescription( description() );
|
|
new_rule->setLogging( logging() );
|
|
new_rule->setEnabled( enabled() );
|
|
new_rule->setTarget( target() );
|
|
TQPtrList<TQString>* available_types = IPTRuleOption::getAvailableOptionTypes();
|
|
TQString type = "";
|
|
TQPtrListIterator<TQString> it( *available_types );
|
|
while ( it.current() ) {
|
|
type = *it.current();
|
|
++it;
|
|
IPTRuleOption* opt = getOptionForName( type );
|
|
IPTRuleOption* clone_opt = new_rule->getOptionForName( type );
|
|
// FIXME: Check For Error
|
|
TQStringList *errors = new TQStringList();
|
|
clone_opt->loadXML( opt->getDOMTree(), *errors );
|
|
}
|
|
}
|
|
|
|
}
|