natefw

natefw Mercurial Source Tree


Root/src/nfw.cpp

#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;
        cout << "regex library by Jeff Stuart (GPL) http://freshmeat.net/projects/cpp_regex/" << endl;
        this->valid = true;
    } else if ( this->paramters.size() == 3 && this->paramters.at(1) == "file" ) {
        //open 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")
                {
                    //this->customRule(rule);
                    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) {
        // parse rule from parameter
        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")
        {
            //this->customRule(rule);
            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)
{
    // Parses a single rule
    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)*"));
 
    //auto_ptr<Matcher> actionmatch = action->createMatcher();
    //auto_ptr<Matcher> ipmatch = ip->createMatcher();
    //auto_ptr<Matcher> iprangematch = iprange->createMatcher();
    for(unsigned int i = 0; i < rule_arr.size(); i++)
    {
        parts = split->findAll(rule_arr.at(i));
        //this->split(rule_arr.at(i), ' ', parts);
        //rule_arr.spl
        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 {
            //parse the other rules that we won't bother matching with regex
            if (p1 == "comment")
            {
                //strip qoutes if exists
                if (p2.at(0) == '"')
                {
                    p2.erase(0,1);
                    p2.erase(p2.size() - 1, 1);
                }
                //p2.replace(p2.find("\""), 1, "");
                //p2.replace(p2.find("\""), 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()
{
    // It doesn't seem to like (word|word) regex syntax, perhaps time to find a new regex library?
    //this->grammar.push_back("(\\w)* (input|output|forward){1}"); // <action> <chain>
    this->grammar.push_back("(\\w)* (\\w)*"); // <action> <chain>
    this->grammar.push_back("(?:\\d{1,3}\\.){3}\\d{1,3} (source|destination)"); // <ip> =: <ip_addr> <direction>
    this->grammar.push_back("(?:\\d{1,3}\\.){3}\\d{1,3}-(?:\\d{1,3}\\.){3}\\d{1,3} (source|destitation)"); // <iprange> =: <ip_addr>-<ip_addr> <direction>
    //this->grammar.push_back("(\\d)* (source|destitation)");//<port> =: # <direction>
    //this->grammar.push_back("recent (day|year|month)-(\\d)*-(\\d)*"); // <recent> =: recent <time>-#-#
    this->grammar.push_back("(\\d)* (\\w)*");//<port> =: # <direction>
    this->grammar.push_back("recent (\\w)*-(\\d)*-(\\d)*"); // <recent> =: recent <time>-#-#
    this->grammar.push_back("name (\\w){1}"); //<name> =: name <string>
    this->grammar.push_back("comment (\\w|\"([^\"]*)\")+"); //<comment> =: comment <string>
    this->grammar.push_back("protocol (tcp|udp)"); //<protocol> =: protocol ( tcp | udp )
    this->grammar.push_back("cstate (new|related|established|invalid)"); // <cstate> =: cstate { NEW | RELATED | ESTABLISHED | INVALID }
    this->grammar.push_back("state (new|related|established|invalid)"); // <state> =: 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);
    }
}

Archive Download this file

Branches

Tags

Page rendered in 1.33748s using 11 queries.