#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <algorithm>
#include <sstream>
#include <fstream>
#include "regexp/Pattern.h"
#include "regexp/Matcher.h"
#include "nfw.h"
using
namespace
std;
nfw::nfw(
int
argc,
char
*argv[])
{
for
(
int
i = 0; i<argc; i++)
this
->paramters.push_back(argv[i]);
this
->populateGrammar();
this
->parseArguments();
}
void
nfw::parseArguments()
{
vector<string> rule_arr;
vector<string> words;
ifstream rulefile;
string line;
string rule;
if
(
this
->paramters.size() == 1)
{
cerr <<
"Wrong number of arguments"
<< endl;
}
else
if
(
this
->paramters.size() == 2 &&
this
->paramters.at(1) ==
"help"
)
{
cout <<
"Some help information..."
<< endl;
this
->valid =
true
;
}
else
if
(
this
->paramters.size() == 2 && (
this
->paramters.at(1) ==
"version"
||
this
->paramters.at(1) ==
"ver"
) )
{
cout <<
"nfw version - "
<< NFW_VERSION << endl;
this
->valid =
true
;
}
else
if
(
this
->paramters.size() == 3 &&
this
->paramters.at(1) ==
"file"
) {
rulefile.open(
this
->paramters.at(2).c_str());
if
(rulefile.is_open())
{
while
(! rulefile.eof() )
{
getline(rulefile, line);
Pattern * p = Pattern::compile(
"([a-z0-9.\\-])+ (\\w|\"([^\"]*)\")+"
);
rule_arr = p->findAll(line);
delete
p;
this
->split(line,
' '
, words);
if
(words.at(0) ==
"custom"
)
{
for
(unsigned
int
i = 1; i < words.size(); i++)
{
cout << words.at(i) <<
" "
;
}
cout << endl;
}
else
{
if
(
this
->validateRules(rule_arr))
{
this
->valid =
true
;
this
->parseRule(rule_arr);
}
else
{
this
->valid =
false
;
}
}
words.clear();
rule_arr.clear();
}
rulefile.close();
}
}
else
if
(
this
->paramters.size() > 3) {
for
(unsigned
int
i = 1; i <
this
->paramters.size(); i++)
{
if
(i ==
this
->paramters.size())
rule +=
this
->paramters.at(i);
else
rule +=
this
->paramters.at(i) +
" "
;
}
Pattern * p = Pattern::compile(
"([a-z0-9.\\-])+ (\\w|\"([^\"]*)\")+"
);
rule_arr = p->findAll(rule);
delete
p;
this
->split(rule,
' '
, words);
if
(words.at(0) ==
"custom"
)
{
for
(unsigned
int
i = 1; i < words.size(); i++)
{
cout << words.at(i) <<
" "
;
}
cout << endl;
}
else
{
if
(
this
->validateRules(rule_arr))
{
this
->valid =
true
;
this
->parseRule(rule_arr);
}
else
{
this
->valid =
false
;
}
}
}
else
{
cerr <<
"Wrong number of arguments"
<< endl;
}
}
void
nfw::parseRule(vector<string>& rule_arr)
{
string p1;
string p2;
string rule =
""
;
string act =
""
;
string chain =
""
;
vector<string> parts;
auto_ptr<Pattern> split(Pattern::compile(
"([a-z0-9.\\-]|\\w|\"([^\"]*)\")+"
));
auto_ptr<Pattern> action(Pattern::compile(
"(drop|deny|accept|log)"
));
auto_ptr<Pattern> ip(Pattern::compile(
"(?:\\d{1,3}\\.){3}\\d{1,3}"
));
auto_ptr<Pattern> iprange(Pattern::compile(
"(?:\\d{1,3}\\.){3}\\d{1,3}-(?:\\d{1,3}\\.){3}\\d{1,3}"
));
auto_ptr<Pattern> port(Pattern::compile(
"(\\d)*"
));
for
(unsigned
int
i = 0; i < rule_arr.size(); i++)
{
parts = split->findAll(rule_arr.at(i));
p1 = parts.at(0);
p2 = parts.at(1);
parts.clear();
Matcher * actionmatch = action->createMatcher(p1);
Matcher * ipmatch = ip->createMatcher(p1);
Matcher * iprangematch = iprange->createMatcher(p1);
Matcher * portmatch = port->createMatcher(p1);
if
(actionmatch->matches())
{
act = p1;
chain = p2;
}
else
if
( iprangematch->matches() )
{
rule +=
"-m iprange "
;
if
(p2 ==
"source"
)
rule +=
"--src-range "
;
else
rule +=
"--dst-range "
;
rule += p1 +
" "
;
}
else
if
( ipmatch->matches() )
{
if
(p2 ==
"source"
)
rule +=
"-s "
;
else
rule +=
"-d "
;
rule += p1 +
" "
;
}
else
if
( portmatch->matches() )
{
if
(p2 ==
"source"
)
rule +=
"--sport "
;
else
rule +=
"--dport "
;
rule += p1 +
" "
;
}
else
{
if
(p1 ==
"comment"
)
{
if
(p2.at(0) ==
'"'
)
{
p2.erase(0,1);
p2.erase(p2.size() - 1, 1);
}
rule +=
"-m comment --comment \""
+ p2 +
"\" "
;
}
else
if
(p1 ==
"protocol"
)
{
rule +=
"-p "
+ p2 +
" "
;
}
}
delete
actionmatch;
delete
ipmatch;
delete
iprangematch;
}
transform(chain.begin(), chain.end(), chain.begin(), ::
toupper
);
transform(act.begin(), act.end(), act.begin(), ::
toupper
);
cout <<
"-A "
<< chain <<
" "
<< rule <<
"-j "
<< act << endl;
}
void
nfw::populateGrammar()
{
this
->grammar.push_back(
"(\\w)* (\\w)*"
);
this
->grammar.push_back(
"(?:\\d{1,3}\\.){3}\\d{1,3} (source|destination)"
);
this
->grammar.push_back(
"(?:\\d{1,3}\\.){3}\\d{1,3}-(?:\\d{1,3}\\.){3}\\d{1,3} (source|destitation)"
);
this
->grammar.push_back(
"(\\d)* (\\w)*"
);
this
->grammar.push_back(
"recent (\\w)*-(\\d)*-(\\d)*"
);
this
->grammar.push_back(
"name (\\w){1}"
);
this
->grammar.push_back(
"comment (\\w|\"([^\"]*)\")+"
);
this
->grammar.push_back(
"protocol (tcp|udp)"
);
this
->grammar.push_back(
"cstate (new|related|established|invalid)"
);
this
->grammar.push_back(
"state (new|related|established|invalid)"
);
}
bool
nfw::isValid()
{
return
this
->valid;
}
string nfw::getFalidRule()
{
return
this
->failedrule;
}
bool
nfw::validateRules(vector<std :: string> & rule_arr)
{
for
(unsigned
int
i = 0; i < rule_arr.size(); i++)
{
bool
goodrule =
false
;
for
(unsigned
int
x = 0; x <
this
->grammar.size(); x++)
{
Pattern * grammar_pat = Pattern::compile(
this
->grammar.at(x));
Matcher * grammar_match = grammar_pat->createMatcher(rule_arr.at(i));
if
(grammar_match->matches())
{
goodrule =
true
;
break
;
}
delete
grammar_pat;
delete
grammar_match;
}
if
(goodrule ==
false
)
{
this
->failedrule = rule_arr.at(i);
return
false
;
}
}
return
true
;
}
void
nfw::split(
const
std::string &s,
char
delim, std::vector<std::string> &elems)
{
std::stringstream ss(s);
std::string item;
while
(std::getline(ss, item, delim)) {
elems.push_back(item);
}
}