support for multiple rule sets in PF

This commit is contained in:
Vadim Kurland
2008-05-30 22:00:45 +00:00
parent 2f9e82c5ba
commit 0457709b97
8 changed files with 1903 additions and 1399 deletions
+12
View File
@@ -1,3 +1,15 @@
2008-05-30 Vadim Kurland <vadim@vk.crocodile.org>
* pf.cpp (main): Like compiler for iptables, compiler for PF now
supports multiple rule sets for policy and nat. Each rule set is
translated into corresponding anchor .conf file. If some rule in
another rule set references it via action Branch, corresponding
"anchor" configuration line is generated, but if it is not
references from any rule, the anchor .conf file is still
created. Rule sets "Policy" and "NAT" are configured "main" or
"root" and placed in the main .conf file with the name of the
firewall object.
2008-05-29 Vadim Kurland <vadim@vk.crocodile.org> 2008-05-29 Vadim Kurland <vadim@vk.crocodile.org>
* ipt.cpp (main): Compiler for iptables processes all Policy and * ipt.cpp (main): Compiler for iptables processes all Policy and
+2 -2
View File
@@ -596,14 +596,14 @@ _("Dynamic interface %s should not have an IP address object attached to it. Thi
n.setHaveDynamicInterfaces(have_dynamic_interfaces); n.setHaveDynamicInterfaces(have_dynamic_interfaces);
if (test_mode) n.setTestMode(); if (test_mode) n.setTestMode();
have_nat = (have_nat || ((nat_rules_count=n.prolog()) > 0));
if ( (nat_rules_count=n.prolog()) > 0 ) if ( (nat_rules_count=n.prolog()) > 0 )
{ {
n.compile(); n.compile();
n.epilog(); n.epilog();
} }
have_nat = (have_nat || (nat_rules_count > 0));
if (n.getCompiledScriptLength() > 0) if (n.getCompiledScriptLength() > 0)
{ {
n_str << "# ================ Table 'nat', rule set " n_str << "# ================ Table 'nat', rule set "
+344 -313
View File
@@ -70,6 +70,7 @@
#include "fwbuilder/Firewall.h" #include "fwbuilder/Firewall.h"
#include "fwbuilder/Interface.h" #include "fwbuilder/Interface.h"
#include "fwbuilder/Policy.h" #include "fwbuilder/Policy.h"
#include "fwbuilder/NAT.h"
#ifdef HAVE_GETOPT_H #ifdef HAVE_GETOPT_H
#include <getopt.h> #include <getopt.h>
@@ -102,8 +103,18 @@ static bool test_mode = false;
static bool ipv4_run = true; static bool ipv4_run = true;
static bool ipv6_run = true; static bool ipv6_run = true;
static map<string,RuleSet*> branches; // Note that in the following maps ruleset name will be
static map<string,string> anchor_files; // "__main__" for both main Policy and NAT rulesets.
// map ruleset_name -> conf file name
static map<string, string> conf_files;
// map ruleset_name -> generated script
static map<string, ostringstream*> generated_scripts;
// map ruleset_name -> TableFactory*
static map<string, TableFactory*> table_factories;
FWObjectDatabase *objdb = NULL; FWObjectDatabase *objdb = NULL;
@@ -134,6 +145,30 @@ void join::operator()(std::string &s)
*result += s; *result += s;
} }
string getConfFileName(const string &ruleset_name,
const string &fwobjectname,
const string &fw_file_name)
{
string conf_file_name;
if (ruleset_name == "__main__")
conf_file_name = string(fwobjectname) + ".conf";
else
{
if (fw_file_name.empty())
{
conf_file_name = string(fwobjectname) + "-" +
ruleset_name + ".conf";
} else
{
string::size_type n = fw_file_name.rfind(".");
conf_file_name = fw_file_name;
conf_file_name.erase(n);
conf_file_name.append("-" + ruleset_name + ".conf");
}
}
return conf_file_name;
}
void usage(const char *name) void usage(const char *name)
{ {
cout << _("Firewall Builder: policy compiler for OpenBSD PF") << endl; cout << _("Firewall Builder: policy compiler for OpenBSD PF") << endl;
@@ -168,6 +203,191 @@ void printProlog(ofstream &file, const string &prolog_code)
file << "#" << endl; file << "#" << endl;
} }
void printStaticOptions(ofstream &file, Firewall* fw)
{
FWOptions* options = fw->getOptionsObject();
list<FWObject*> all_interfaces=fw->getByType(Interface::TYPENAME);
string prolog_place = options->getStr("prolog_place");
if (prolog_place.empty()) prolog_place = "fw_file"; // old default
string pre_hook = options->getStr("prolog_script");
if (prolog_place == "pf_file_top")
printProlog(file, pre_hook);
file << endl;
list<string> limits;
if (options->getBool("pf_do_limit_frags") &&
options->getInt("pf_limit_frags")>0 )
limits.push_back(string("frags ") +
options->getStr("pf_limit_frags"));
if (options->getBool("pf_do_limit_states") &&
options->getInt("pf_limit_states")>0 )
limits.push_back(string("states ") +
options->getStr("pf_limit_states"));
if (options->getBool("pf_do_limit_src_nodes") &&
options->getInt("pf_limit_src_nodes")>0 )
limits.push_back(string("src-nodes ") +
options->getStr("pf_limit_src_nodes"));
if (options->getBool("pf_do_limit_tables") &&
options->getInt("pf_limit_tables")>0 )
limits.push_back(string("tables ") +
options->getStr("pf_limit_tables"));
if (options->getBool("pf_do_limit_table_entries") &&
options->getInt("pf_limit_table_entries")>0 )
limits.push_back(string("table-entries ") +
options->getStr("pf_limit_table_entries"));
if (limits.size() > 0)
{
file << "set limit ";
if (limits.size() > 1 ) file << "{ ";
string all_limits;
for_each(limits.begin(), limits.end(), join( &all_limits, ", "));
file << all_limits;
if (limits.size() > 1 ) file << " }";
file << endl;
}
if ( ! options->getStr("pf_optimization").empty() )
file << "set optimization "
<< options->getStr("pf_optimization") << endl;
file << printTimeout(options,
"pf_do_timeout_interval","pf_timeout_interval",
"interval");
file << printTimeout(options,
"pf_do_timeout_frag","pf_timeout_frag",
"frag");
file << printTimeout(options,
"pf_set_tcp_first","pf_tcp_first",
"tcp.first" );
file << printTimeout(options,
"pf_set_tcp_opening","pf_tcp_opening",
"tcp.opening" );
file << printTimeout(options,
"pf_set_tcp_established","pf_tcp_established",
"tcp.established" );
file << printTimeout(options,
"pf_set_tcp_closing","pf_tcp_closing",
"tcp.closing" );
file << printTimeout(options,
"pf_set_tcp_finwait","pf_tcp_finwait",
"tcp.finwait" );
file << printTimeout(options,
"pf_set_tcp_closed","pf_tcp_closed",
"tcp.closed" );
file << printTimeout(options,
"pf_set_udp_first","pf_udp_first",
"udp.first" );
file << printTimeout(options,
"pf_set_udp_single","pf_udp_single",
"udp.single" );
file << printTimeout(options,
"pf_set_udp_multiple","pf_udp_multiple",
"udp.multiple" );
file << printTimeout(options,
"pf_set_icmp_first","pf_icmp_first",
"icmp.first" );
file << printTimeout(options,
"pf_set_icmp_error","pf_icmp_error",
"icmp.error" );
file << printTimeout(options,
"pf_set_other_first","pf_other_first",
"other.first" );
file << printTimeout(options,
"pf_set_other_single","pf_other_single",
"other.single" );
file << printTimeout(options,
"pf_set_other_multiple","pf_other_multiple",
"other.multiple" );
file << printTimeout(options,
"pf_set_adaptive","pf_adaptive_start",
"adaptive.start" );
file << printTimeout(options,
"pf_set_adaptive","pf_adaptive_end",
"adaptive.end");
// check if any interface is marked as 'unprotected'
// and generate 'set skip on <ifspec>' commands
if (fw->getStr("version")=="ge_3.7" ||
fw->getStr("version")=="4.x")
{
for (list<FWObject*>::iterator i=all_interfaces.begin();
i!=all_interfaces.end(); ++i)
{
Interface *iface=dynamic_cast<Interface*>(*i);
assert(iface);
if ( iface->isUnprotected())
file << "set skip on " << iface->getName() << endl;
}
}
file << endl;
if (prolog_place == "pf_file_after_set")
printProlog(file, pre_hook);
string scrub_options;
if (options->getBool("pf_do_scrub"))
{
if (options->getBool("pf_scrub_reassemble"))
scrub_options+="fragment reassemble ";
else
{
if (options->getBool("pf_scrub_fragm_crop"))
scrub_options+="fragment crop ";
else
{
if (options->getBool("pf_scrub_fragm_drop_ovl"))
scrub_options+="fragment drop-ovl ";
}
}
}
if (options->getBool("pf_scrub_no_df")) scrub_options+="no-df ";
if (!scrub_options.empty())
{
file << "#" << endl;
file << "# Scrub rules" << endl;
file << "#" << endl;
file << "scrub in all " << scrub_options << endl;
}
scrub_options="";
if (options->getBool("pf_scrub_random_id"))
scrub_options+="random-id ";
if (options->getBool("pf_scrub_use_minttl"))
scrub_options+="min-ttl " + options->getStr("pf_scrub_minttl") + " ";
if (options->getBool("pf_scrub_use_maxmss"))
scrub_options+="max-mss " + options->getStr("pf_scrub_maxmss") + " ";
if (!scrub_options.empty())
{
file << "scrub out all " << scrub_options << endl;
}
file << endl;
if (prolog_place == "pf_file_after_scrub")
printProlog(file, pre_hook);
//file << table_factory->PrintTables();
//file << endl;
if (prolog_place == "pf_file_after_tables")
printProlog(file, pre_hook);
}
int main(int argc, char * const *argv) int main(int argc, char * const *argv)
{ {
@@ -416,9 +636,12 @@ int main(int argc, char * const *argv)
oscnf->prolog(); oscnf->prolog();
list<FWObject*> all_policies = fw->getByType(Policy::TYPENAME);
list<FWObject*> all_nat = fw->getByType(NAT::TYPENAME);
vector<bool> ipv4_6_runs; vector<bool> ipv4_6_runs;
string generated_script; bool have_nat = false;
bool have_pf = false;
// command line options -4 and -6 control address family for which // command line options -4 and -6 control address family for which
// script will be generated. If "-4" is used, only ipv4 part will // script will be generated. If "-4" is used, only ipv4 part will
@@ -440,347 +663,153 @@ int main(int argc, char * const *argv)
if (ipv4_run) ipv4_6_runs.push_back(false); if (ipv4_run) ipv4_6_runs.push_back(false);
} }
ostringstream *main_str = new ostringstream();
for (vector<bool>::iterator i=ipv4_6_runs.begin(); for (vector<bool>::iterator i=ipv4_6_runs.begin();
i!=ipv4_6_runs.end(); ++i) i!=ipv4_6_runs.end(); ++i)
{ {
bool ipv6_policy = *i; bool ipv6_policy = *i;
if (ipv6_policy)
{
generated_script += "\n\n";
generated_script += "#================ IPv6 ================\n";
generated_script += "\n\n";
} else
{
generated_script += "\n\n";
generated_script += "#================ IPv4 ================\n";
generated_script += "\n\n";
}
TableFactory *table_factory = new TableFactory();
Preprocessor_pf* prep = new Preprocessor_pf( Preprocessor_pf* prep = new Preprocessor_pf(
objdb , fwobjectname, ipv6_policy); objdb , fwobjectname, ipv6_policy);
prep->compile(); prep->compile();
// find branching rules and store names of the branches and list<NATCompiler_pf::redirectRuleInfo> redirect_rules_info;
// pointers to corresponding rule sets
// for (list<FWObject*>::iterator p=all_nat.begin();
FWObject *policy = fw->getFirstByType(Policy::TYPENAME); p!=all_nat.end(); ++p )
for (FWObject::iterator i=policy->begin(); i!=policy->end(); i++)
{ {
PolicyRule *rule = PolicyRule::cast(*i); NAT *nat = NAT::cast(*p);
if (rule->getAction()==PolicyRule::Branch) string ruleset_name = nat->getName();
if (Compiler::isRootRuleSet(nat))
ruleset_name = "__main__";
if (!table_factories.count(ruleset_name))
table_factories[ruleset_name] = new TableFactory();
NATCompiler_pf n( objdb, fwobjectname, ipv6_policy, oscnf,
table_factories[ruleset_name] );
n.setSourceRuleSet( nat );
n.setRuleSetName(nat->getName());
n.setDebugLevel( dl );
n.setDebugRule( drn );
n.setVerbose( verbose );
if (test_mode) n.setTestMode();
int nat_rules_count = 0;
if ( (nat_rules_count=n.prolog()) > 0 )
{ {
int parentRuleNum = rule->getPosition(); n.compile();
RuleSet *subset = rule->getBranch(); n.epilog();
if (subset==NULL)
{
throw FWException(
_("Action 'Branch' but no branch policy in policy rule ")
+rule->getLabel());
}
subset->setInt("parent_rule_num",parentRuleNum);
FWOptions *ropt = rule->getOptionsObject();
string branchName = ropt->getStr("branch_name");
branches[branchName] = subset;
subset->ref();
rule->remove(subset);
} }
have_nat = (have_nat || (nat_rules_count > 0));
if (Compiler::isRootRuleSet(nat))
{
generated_scripts[ruleset_name] = main_str;
} else
{
generated_scripts[ruleset_name] = new ostringstream();
}
if (n.getCompiledScriptLength() > 0)
{
*(generated_scripts[ruleset_name]) << n.getCompiledScript();
*(generated_scripts[ruleset_name]) << endl;
}
conf_files[ruleset_name] = getConfFileName(ruleset_name,
fwobjectname,
fw_file_name);
const list<NATCompiler_pf::redirectRuleInfo> lst =
n.getRedirRulesInfo();
redirect_rules_info.insert(redirect_rules_info.begin(),
lst.begin(), lst.end());
} }
NATCompiler_pf n( objdb, fwobjectname, ipv6_policy, oscnf, for (list<FWObject*>::iterator p=all_policies.begin();
table_factory ); p!=all_policies.end(); ++p )
n.setDebugLevel( dl );
n.setDebugRule( drn );
n.setVerbose( verbose );
if (test_mode) n.setTestMode();
bool have_nat=false;
if ( n.prolog() > 0 )
{ {
have_nat=true; Policy *policy = Policy::cast(*p);
string ruleset_name = policy->getName();
if (Compiler::isRootRuleSet(policy))
ruleset_name = "__main__";
n.compile(); if (!table_factories.count(ruleset_name))
n.epilog(); table_factories[ruleset_name] = new TableFactory();
}
PolicyCompiler_pf c( objdb, fwobjectname, ipv6_policy, oscnf, PolicyCompiler_pf c( objdb, fwobjectname, ipv6_policy, oscnf,
&n, table_factory ); &redirect_rules_info,
table_factories[ruleset_name] );
c.setDebugLevel( dl ); c.setSourceRuleSet( policy );
c.setDebugRule( drp ); c.setRuleSetName(policy->getName());
c.setVerbose( verbose );
if (test_mode) c.setTestMode();
bool have_pf=false;
if ( c.prolog() > 0 )
{
have_pf=true;
cout << " Compiling policy rules for "
<< fwobjectname
<< " ..." << endl << flush;
c.compile();
c.epilog();
}
generated_script += table_factory->PrintTables();
generated_script += "\n";
if (have_nat) generated_script += n.getCompiledScript();
if (have_pf) generated_script += c.getCompiledScript();
// run policy compiler for each branch we have found in the
// ruleset and store the result in a separate .conf file
//
map<string,RuleSet*>::iterator bi;
for (bi=branches.begin(); bi!=branches.end(); ++bi)
{
table_factory = new TableFactory();
string branchName = bi->first;
RuleSet *subset = bi->second;
PolicyCompiler_pf c( objdb , fwobjectname, ipv6_policy,
oscnf, &n, table_factory );
c.setSourceRuleSet( subset );
c.setRuleSetName(branchName);
c.setDebugLevel( dl ); c.setDebugLevel( dl );
c.setDebugRule( drp ); c.setDebugRule( drp );
c.setVerbose( verbose ); c.setVerbose( verbose );
if (test_mode) c.setTestMode(); if (test_mode) c.setTestMode();
if ( c.prolog() > 0 ) int pf_rules_count = 0;
if ( (pf_rules_count=c.prolog()) > 0 )
{ {
cout << " Compiling rules for anchor "
<< branchName
<< " ..." << endl << flush;
c.compile(); c.compile();
c.epilog(); c.epilog();
string anchor_file_name;
if (fw_file_name.empty())
{
anchor_file_name=string(fwobjectname) + "-" + branchName + ".conf";
} else
{
string::size_type n = fw_file_name.rfind(".");
anchor_file_name = fw_file_name;
anchor_file_name.erase(n);
anchor_file_name.append("-" + branchName + ".conf");
}
anchor_files[branchName] = anchor_file_name;
ofstream pf_file;
pf_file.exceptions(ofstream::eofbit|ofstream::failbit|ofstream::badbit);
#ifdef _WIN32
pf_file.open(anchor_file_name.c_str(), ios::out|ios::binary);
#else
pf_file.open(anchor_file_name.c_str());
#endif
pf_file << endl;
pf_file << table_factory->PrintTables();
pf_file << endl;
pf_file << c.getCompiledScript();
pf_file.close();
} }
have_pf = (have_pf || (pf_rules_count > 0));
if (Compiler::isRootRuleSet(policy))
{
generated_scripts[ruleset_name] = main_str;
} else
{
generated_scripts[ruleset_name] = new ostringstream();
}
if (c.getCompiledScriptLength() > 0)
{
*(generated_scripts[ruleset_name]) << c.getCompiledScript();
*(generated_scripts[ruleset_name]) << endl;
}
conf_files[ruleset_name] = getConfFileName(ruleset_name,
fwobjectname,
fw_file_name);
} }
} }
/* /*
* now write generated scripts to files * now write generated scripts to files
*/ */
for (map<string, ostringstream*>::iterator fi=generated_scripts.begin();
fi!=generated_scripts.end(); fi++)
{
string ruleset_name = fi->first;
string file_name = conf_files[ruleset_name];
ostringstream *strm = fi->second;
ofstream pf_file; ofstream pf_file;
pf_file.exceptions(ofstream::eofbit|ofstream::failbit|ofstream::badbit); pf_file.exceptions(
ofstream::eofbit|ofstream::failbit|ofstream::badbit);
#ifdef _WIN32 #ifdef _WIN32
pf_file.open(pf_file_name.c_str(), ios::out|ios::binary); pf_file.open(file_name.c_str(), ios::out|ios::binary);
#else #else
pf_file.open(pf_file_name.c_str()); pf_file.open(file_name.c_str());
#endif #endif
if (prolog_place == "pf_file_top") if (ruleset_name == "__main__")
printProlog(pf_file, pre_hook);
pf_file << endl;
list<string> limits;
if (options->getBool("pf_do_limit_frags") &&
options->getInt("pf_limit_frags")>0 )
limits.push_back(string("frags ") +
options->getStr("pf_limit_frags"));
if (options->getBool("pf_do_limit_states") &&
options->getInt("pf_limit_states")>0 )
limits.push_back(string("states ") +
options->getStr("pf_limit_states"));
if (options->getBool("pf_do_limit_src_nodes") &&
options->getInt("pf_limit_src_nodes")>0 )
limits.push_back(string("src-nodes ") +
options->getStr("pf_limit_src_nodes"));
if (options->getBool("pf_do_limit_tables") &&
options->getInt("pf_limit_tables")>0 )
limits.push_back(string("tables ") +
options->getStr("pf_limit_tables"));
if (options->getBool("pf_do_limit_table_entries") &&
options->getInt("pf_limit_table_entries")>0 )
limits.push_back(string("table-entries ") +
options->getStr("pf_limit_table_entries"));
if (limits.size() > 0)
{
pf_file << "set limit ";
if (limits.size() > 1 ) pf_file << "{ ";
string all_limits;
for_each(limits.begin(), limits.end(), join( &all_limits, ", "));
pf_file << all_limits;
if (limits.size() > 1 ) pf_file << " }";
pf_file << endl;
}
if ( ! options->getStr("pf_optimization").empty() )
pf_file << "set optimization "
<< options->getStr("pf_optimization") << endl;
pf_file << printTimeout(options,
"pf_do_timeout_interval","pf_timeout_interval",
"interval");
pf_file << printTimeout(options,
"pf_do_timeout_frag","pf_timeout_frag",
"frag");
pf_file << printTimeout(options,
"pf_set_tcp_first","pf_tcp_first",
"tcp.first" );
pf_file << printTimeout(options,
"pf_set_tcp_opening","pf_tcp_opening",
"tcp.opening" );
pf_file << printTimeout(options,
"pf_set_tcp_established","pf_tcp_established",
"tcp.established" );
pf_file << printTimeout(options,
"pf_set_tcp_closing","pf_tcp_closing",
"tcp.closing" );
pf_file << printTimeout(options,
"pf_set_tcp_finwait","pf_tcp_finwait",
"tcp.finwait" );
pf_file << printTimeout(options,
"pf_set_tcp_closed","pf_tcp_closed",
"tcp.closed" );
pf_file << printTimeout(options,
"pf_set_udp_first","pf_udp_first",
"udp.first" );
pf_file << printTimeout(options,
"pf_set_udp_single","pf_udp_single",
"udp.single" );
pf_file << printTimeout(options,
"pf_set_udp_multiple","pf_udp_multiple",
"udp.multiple" );
pf_file << printTimeout(options,
"pf_set_icmp_first","pf_icmp_first",
"icmp.first" );
pf_file << printTimeout(options,
"pf_set_icmp_error","pf_icmp_error",
"icmp.error" );
pf_file << printTimeout(options,
"pf_set_other_first","pf_other_first",
"other.first" );
pf_file << printTimeout(options,
"pf_set_other_single","pf_other_single",
"other.single" );
pf_file << printTimeout(options,
"pf_set_other_multiple","pf_other_multiple",
"other.multiple" );
pf_file << printTimeout(options,
"pf_set_adaptive","pf_adaptive_start",
"adaptive.start" );
pf_file << printTimeout(options,
"pf_set_adaptive","pf_adaptive_end",
"adaptive.end");
// check if any interface is marked as 'unprotected'
// and generate 'set skip on <ifspec>' commands
if (fw->getStr("version")=="ge_3.7" ||
fw->getStr("version")=="4.x")
{
for (list<FWObject*>::iterator i=all_interfaces.begin();
i!=all_interfaces.end(); ++i)
{ {
Interface *iface=dynamic_cast<Interface*>(*i); printStaticOptions(pf_file, fw);
assert(iface);
if ( iface->isUnprotected())
pf_file << "set skip on " << iface->getName() << endl;
} }
pf_file << table_factories[ruleset_name]->PrintTables();
pf_file << strm->str();
pf_file.close();
} }
pf_file << endl;
if (prolog_place == "pf_file_after_set")
printProlog(pf_file, pre_hook);
string scrub_options;
if (options->getBool("pf_do_scrub"))
{
if (options->getBool("pf_scrub_reassemble"))
scrub_options+="fragment reassemble ";
else
{
if (options->getBool("pf_scrub_fragm_crop"))
scrub_options+="fragment crop ";
else
{
if (options->getBool("pf_scrub_fragm_drop_ovl"))
scrub_options+="fragment drop-ovl ";
}
}
}
if (options->getBool("pf_scrub_no_df")) scrub_options+="no-df ";
if (!scrub_options.empty())
{
pf_file << "#" << endl;
pf_file << "# Scrub rules" << endl;
pf_file << "#" << endl;
pf_file << "scrub in all " << scrub_options << endl;
}
scrub_options="";
if (options->getBool("pf_scrub_random_id")) scrub_options+="random-id ";
if (options->getBool("pf_scrub_use_minttl")) scrub_options+="min-ttl " + options->getStr("pf_scrub_minttl") + " ";
if (options->getBool("pf_scrub_use_maxmss")) scrub_options+="max-mss " + options->getStr("pf_scrub_maxmss") + " ";
if (!scrub_options.empty())
{
pf_file << "scrub out all " << scrub_options << endl;
}
pf_file << endl;
if (prolog_place == "pf_file_after_scrub")
printProlog(pf_file, pre_hook);
//pf_file << table_factory->PrintTables();
//pf_file << endl;
if (prolog_place == "pf_file_after_tables")
printProlog(pf_file, pre_hook);
pf_file << generated_script;
pf_file.close();
char *timestr; char *timestr;
time_t tm; time_t tm;
struct tm *stm; struct tm *stm;
@@ -826,9 +855,9 @@ int main(int argc, char * const *argv)
<< user_name << "\n#\n"; << user_name << "\n#\n";
fw_file << MANIFEST_MARKER << "* " << fw_file_name << endl; fw_file << MANIFEST_MARKER << "* " << fw_file_name << endl;
fw_file << MANIFEST_MARKER << " " << pf_file_name << endl; //fw_file << MANIFEST_MARKER << " " << pf_file_name << endl;
for (map<string,string>::iterator i=anchor_files.begin(); for (map<string,string>::iterator i=conf_files.begin();
i!=anchor_files.end(); ++i) i!=conf_files.end(); ++i)
fw_file << MANIFEST_MARKER << " " << i->second << endl; fw_file << MANIFEST_MARKER << " " << i->second << endl;
fw_file << "#" << endl; fw_file << "#" << endl;
@@ -869,15 +898,17 @@ int main(int argc, char * const *argv)
<< " || exit 1" << " || exit 1"
<< endl; << endl;
for (map<string,string>::iterator i=anchor_files.begin(); for (map<string,string>::iterator i=conf_files.begin();
i!=anchor_files.end(); ++i) i!=conf_files.end(); ++i)
fw_file << "$PFCTL " << pfctl_dbg {
<< "-a " << i->first << " " if (i->first != "__main__")
<< pfctl_f_option fw_file << "$PFCTL " << pfctl_dbg
<< "${FWDIR}/" << i->second << "-a " << i->first << " "
<< " || exit 1" << pfctl_f_option
<< endl; << "${FWDIR}/" << i->second
<< " || exit 1"
<< endl;
}
fw_file << endl; fw_file << endl;
fw_file << "#" << endl; fw_file << "#" << endl;
fw_file << "# Epilog script" << endl; fw_file << "# Epilog script" << endl;
+10 -3
View File
@@ -102,7 +102,12 @@ int NATCompiler_pf::prolog()
dbcopy->add(loopback_address,false); dbcopy->add(loopback_address,false);
cacheObj(loopback_address); cacheObj(loopback_address);
if (tables) tables->init(dbcopy); if (tables)
{
tables->init(dbcopy);
if (!isRootRuleSet(getSourceRuleSet()))
tables->setRuleSetName(getRuleSetName());
}
return n; return n;
} }
@@ -906,8 +911,10 @@ void NATCompiler_pf::compile()
{ {
bool manage_virtual_addr=fwopt->getBool("manage_virtual_addr"); bool manage_virtual_addr=fwopt->getBool("manage_virtual_addr");
cout << " Compiling " << fw->getName();
cout << _(" Compiling NAT rules for ") << fw->getName() << " ..." << endl << flush; if (!getRuleSetName().empty()) cout << " ruleset " << getRuleSetName();
if (ipv6) cout << ", IPv6";
cout << endl << flush;
try { try {
+129 -114
View File
@@ -83,7 +83,8 @@ int PolicyCompiler_pf::prolog()
if (tables) if (tables)
{ {
tables->init(dbcopy); tables->init(dbcopy);
tables->setRuleSetName(getRuleSetName()); if (!isRootRuleSet(getSourceRuleSet()))
tables->setRuleSetName(getRuleSetName());
} }
return PolicyCompiler::prolog(); return PolicyCompiler::prolog();
@@ -374,133 +375,138 @@ bool PolicyCompiler_pf::fillDirection::processNext()
*/ */
void PolicyCompiler_pf::addDefaultPolicyRule() void PolicyCompiler_pf::addDefaultPolicyRule()
{ {
if (!getRuleSetName().empty()) return; if (isRootRuleSet(getSourceRuleSet()))
if ( getCachedFwOpt()->getBool("mgmt_ssh") &&
!getCachedFwOpt()->getStr("mgmt_addr").empty() )
{ {
PolicyRule *r; if ( getCachedFwOpt()->getBool("mgmt_ssh") &&
TCPService *ssh=TCPService::cast(dbcopy->create(TCPService::TYPENAME) ); !getCachedFwOpt()->getStr("mgmt_addr").empty() )
ssh->setInt("dst_range_start",22);
ssh->setInt("dst_range_end",22);
ssh->setName("mgmt_ssh");
dbcopy->add(ssh,false);
cacheObj(ssh); // to keep cache consistent
string mgmt_addr = getCachedFwOpt()->getStr("mgmt_addr");
InetAddr addr;
InetAddr netmask(InetAddr::getAllOnes());
try
{ {
addr = InetAddr(mgmt_addr); PolicyRule *r;
string::size_type sep = mgmt_addr.find("/"); TCPService *ssh =
if (sep != string::npos) TCPService::cast(dbcopy->create(TCPService::TYPENAME) );
ssh->setInt("dst_range_start",22);
ssh->setInt("dst_range_end",22);
ssh->setName("mgmt_ssh");
dbcopy->add(ssh,false);
cacheObj(ssh); // to keep cache consistent
string mgmt_addr = getCachedFwOpt()->getStr("mgmt_addr");
InetAddr addr;
InetAddr netmask(InetAddr::getAllOnes());
try
{ {
addr = InetAddr(mgmt_addr.substr(0,sep)); addr = InetAddr(mgmt_addr);
string nm = mgmt_addr.substr(sep+1); string::size_type sep = mgmt_addr.find("/");
int o1,o2,o3,o4; if (sep != string::npos)
if(sscanf(nm.c_str(), "%3u.%3u.%3u.%3u", &o1, &o2, &o3, &o4)==4)
{ {
netmask = InetAddr(nm); addr = InetAddr(mgmt_addr.substr(0,sep));
} else string nm = mgmt_addr.substr(sep+1);
{ int o1,o2,o3,o4;
sscanf(nm.c_str(),"%u",&o1); if (sscanf(nm.c_str(),
netmask = InetAddr(o1); "%3u.%3u.%3u.%3u", &o1, &o2, &o3, &o4)==4)
{
netmask = InetAddr(nm);
} else
{
sscanf(nm.c_str(),"%u",&o1);
netmask = InetAddr(o1);
}
} }
} catch(FWException &ex)
{
char errstr[256];
sprintf(errstr,
_("Invalid address for the backup ssh access: '%s'"),
mgmt_addr.c_str() );
abort( errstr );
} }
} catch(FWException &ex)
{
char errstr[256];
sprintf(errstr,
_("Invalid address for the backup ssh access: '%s'"),
mgmt_addr.c_str() );
abort( errstr );
}
Network *mgmt_workstation = Network::cast(dbcopy->create(Network::TYPENAME)); Network *mgmt_workstation =
mgmt_workstation->setName("mgmt_addr"); Network::cast(dbcopy->create(Network::TYPENAME));
mgmt_workstation->setAddress( addr ); mgmt_workstation->setName("mgmt_addr");
mgmt_workstation->setNetmask( netmask ); mgmt_workstation->setAddress( addr );
mgmt_workstation->setNetmask( netmask );
// IPv4 *mgmt_workstation = IPv4::cast(dbcopy->create(IPv4::TYPENAME)); // IPv4 *mgmt_workstation = IPv4::cast(dbcopy->create(IPv4::TYPENAME));
// mgmt_workstation->setAddress( getCachedFwOpt()->getStr("mgmt_addr") ); // mgmt_workstation->setAddress( getCachedFwOpt()->getStr("mgmt_addr") );
dbcopy->add(mgmt_workstation,false); dbcopy->add(mgmt_workstation,false);
cacheObj(mgmt_workstation); // to keep cache consistent cacheObj(mgmt_workstation); // to keep cache consistent
r= PolicyRule::cast(dbcopy->create(PolicyRule::TYPENAME) ); r= PolicyRule::cast(dbcopy->create(PolicyRule::TYPENAME) );
temp_ruleset->add(r); temp_ruleset->add(r);
r->setAction(PolicyRule::Accept); r->setAction(PolicyRule::Accept);
r->setLogging(false); r->setLogging(false);
r->setDirection(PolicyRule::Inbound); r->setDirection(PolicyRule::Inbound);
r->setPosition(9999); r->setPosition(9999);
r->setComment(" backup ssh access rule "); r->setComment(" backup ssh access rule ");
r->setHidden(true); r->setHidden(true);
r->setFallback(false); r->setFallback(false);
r->setLabel("backup ssh access rule"); r->setLabel("backup ssh access rule");
r->setBool("needs_established",true); // supported in ipfw r->setBool("needs_established",true); // supported in ipfw
RuleElement *src=r->getSrc(); RuleElement *src=r->getSrc();
assert(src!=NULL); assert(src!=NULL);
src->addRef(mgmt_workstation); src->addRef(mgmt_workstation);
RuleElement *dst=r->getDst(); RuleElement *dst=r->getDst();
assert(dst!=NULL); assert(dst!=NULL);
dst->addRef(fw); dst->addRef(fw);
RuleElement *srv=r->getSrv(); RuleElement *srv=r->getSrv();
assert(srv!=NULL); assert(srv!=NULL);
srv->addRef(ssh); srv->addRef(ssh);
combined_ruleset->push_front(r); combined_ruleset->push_front(r);
} }
if ( getCachedFwOpt()->getBool("pass_all_out") ) if ( getCachedFwOpt()->getBool("pass_all_out") )
{ {
PolicyRule *r; PolicyRule *r;
FWOptions *ruleopt; FWOptions *ruleopt;
r= PolicyRule::cast(dbcopy->create(PolicyRule::TYPENAME) ); r= PolicyRule::cast(dbcopy->create(PolicyRule::TYPENAME) );
temp_ruleset->add(r); temp_ruleset->add(r);
r->setAction(PolicyRule::Accept); r->setAction(PolicyRule::Accept);
r->setLogging( getCachedFwOpt()->getBool("fallback_log") ); r->setLogging( getCachedFwOpt()->getBool("fallback_log") );
r->setDirection(PolicyRule::Outbound); r->setDirection(PolicyRule::Outbound);
r->setPosition(10000); r->setPosition(10000);
r->setComment(" fallback rule "); r->setComment(" fallback rule ");
r->setHidden(true); r->setHidden(true);
r->setFallback(true); r->setFallback(true);
r->setLabel("fallback rule"); r->setLabel("fallback rule");
combined_ruleset->push_back(r); combined_ruleset->push_back(r);
r= PolicyRule::cast(dbcopy->create(PolicyRule::TYPENAME) ); r= PolicyRule::cast(dbcopy->create(PolicyRule::TYPENAME) );
temp_ruleset->add(r); temp_ruleset->add(r);
r->setAction(PolicyRule::Deny); r->setAction(PolicyRule::Deny);
r->setLogging( getCachedFwOpt()->getBool("fallback_log") ); r->setLogging( getCachedFwOpt()->getBool("fallback_log") );
r->setDirection(PolicyRule::Inbound); r->setDirection(PolicyRule::Inbound);
r->setPosition(10001); r->setPosition(10001);
r->setComment(" fallback rule "); r->setComment(" fallback rule ");
r->setHidden(true); r->setHidden(true);
r->setFallback(true); r->setFallback(true);
r->setLabel("fallback rule"); r->setLabel("fallback rule");
ruleopt = r->getOptionsObject(); ruleopt = r->getOptionsObject();
ruleopt->setBool("stateless", true); ruleopt->setBool("stateless", true);
combined_ruleset->push_back(r); combined_ruleset->push_back(r);
} else } else
{ {
PolicyRule *r= PolicyRule::cast(dbcopy->create(PolicyRule::TYPENAME) ); PolicyRule *r=
FWOptions *ruleopt; PolicyRule::cast(dbcopy->create(PolicyRule::TYPENAME) );
FWOptions *ruleopt;
temp_ruleset->add(r); temp_ruleset->add(r);
r->setAction(PolicyRule::Deny); r->setAction(PolicyRule::Deny);
r->setLogging( getCachedFwOpt()->getBool("fallback_log") ); r->setLogging( getCachedFwOpt()->getBool("fallback_log") );
r->setDirection(PolicyRule::Both); r->setDirection(PolicyRule::Both);
r->setPosition(10000); r->setPosition(10000);
r->setComment(" fallback rule "); r->setComment(" fallback rule ");
r->setHidden(true); r->setHidden(true);
r->setFallback(true); r->setFallback(true);
r->setLabel("fallback rule"); r->setLabel("fallback rule");
ruleopt = r->getOptionsObject(); ruleopt = r->getOptionsObject();
ruleopt->setBool("stateless", true); ruleopt->setBool("stateless", true);
combined_ruleset->push_back(r); combined_ruleset->push_back(r);
}
} }
} }
@@ -719,14 +725,17 @@ bool PolicyCompiler_pf::addLoopbackForRedirect::processNext()
RuleElementDst *dst=rule->getDst(); RuleElementDst *dst=rule->getDst();
RuleElementSrv *srv=rule->getSrv(); RuleElementSrv *srv=rule->getSrv();
if (pf_comp->natcmp==NULL) if (pf_comp->redirect_rules_info==NULL)
compiler->abort("addLoopbackForRedirect needs a valid pointer to the NAT compiler object"); compiler->abort(
"addLoopbackForRedirect needs a valid pointer to "
"the list<NATCompiler_pf::redirectRuleInfo> object");
tmp_queue.push_back(rule); tmp_queue.push_back(rule);
const list<NATCompiler_pf::redirectRuleInfo> lst=pf_comp->natcmp->getRedirRulesInfo(); //const list<NATCompiler_pf::redirectRuleInfo> lst =
// pf_comp->natcmp->getRedirRulesInfo();
if (lst.empty()) return true; if (pf_comp->redirect_rules_info->empty()) return true;
/* /*
* struct redirectRuleInfo { * struct redirectRuleInfo {
@@ -751,7 +760,8 @@ bool PolicyCompiler_pf::addLoopbackForRedirect::processNext()
assert(a); assert(a);
list<NATCompiler_pf::redirectRuleInfo>::const_iterator k; list<NATCompiler_pf::redirectRuleInfo>::const_iterator k;
for (k=lst.begin(); k!=lst.end(); ++k) for (k=pf_comp->redirect_rules_info->begin();
k!=pf_comp->redirect_rules_info->end(); ++k)
{ {
if ( *a == *(k->old_tdst) && *s == *(k->tsrv) ) if ( *a == *(k->old_tdst) && *s == *(k->tsrv) )
{ {
@@ -942,6 +952,11 @@ bool PolicyCompiler_pf::printScrubRule::processNext()
void PolicyCompiler_pf::compile() void PolicyCompiler_pf::compile()
{ {
cout << " Compiling " << fw->getName();
if (!getRuleSetName().empty()) cout << " ruleset " << getRuleSetName();
if (ipv6) cout << ", IPv6";
cout << endl << flush;
try try
{ {
Compiler::compile(); Compiler::compile();
+4 -6
View File
@@ -29,6 +29,7 @@
#include <fwbuilder/libfwbuilder-config.h> #include <fwbuilder/libfwbuilder-config.h>
#include "fwcompiler/PolicyCompiler.h" #include "fwcompiler/PolicyCompiler.h"
#include "NATCompiler_pf.h"
#include "TableFactory.h" #include "TableFactory.h"
namespace libfwbuilder { namespace libfwbuilder {
@@ -45,8 +46,6 @@ namespace libfwbuilder {
namespace fwcompiler { namespace fwcompiler {
class NATCompiler_pf;
class PolicyCompiler_pf : public PolicyCompiler { class PolicyCompiler_pf : public PolicyCompiler {
public: public:
@@ -442,11 +441,11 @@ namespace fwcompiler {
const std::string &fwname, const std::string &fwname,
bool ipv6_policy, bool ipv6_policy,
fwcompiler::OSConfigurator *_oscnf, fwcompiler::OSConfigurator *_oscnf,
NATCompiler_pf *_natcmp, const std::list<NATCompiler_pf::redirectRuleInfo> *rri,
TableFactory *tbf = NULL) : TableFactory *tbf = NULL) :
PolicyCompiler(_db, fwname, ipv6_policy, _oscnf) PolicyCompiler(_db, fwname, ipv6_policy, _oscnf)
{ {
natcmp=_natcmp; redirect_rules_info = rri;
tables = tbf; tables = tbf;
} }
@@ -457,9 +456,8 @@ namespace fwcompiler {
protected: protected:
TableFactory *tables; TableFactory *tables;
NATCompiler_pf *natcmp;
libfwbuilder::IPv4 *loopback_address; libfwbuilder::IPv4 *loopback_address;
const std::list<NATCompiler_pf::redirectRuleInfo> *redirect_rules_info;
private: private:
+13 -9
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE FWObjectDatabase SYSTEM "fwbuilder.dtd"> <!DOCTYPE FWObjectDatabase SYSTEM "fwbuilder.dtd">
<FWObjectDatabase xmlns="http://www.fwbuilder.org/1.0/" version="7" lastModified="1212115906" id="root"> <FWObjectDatabase xmlns="http://www.fwbuilder.org/1.0/" version="7" lastModified="1212118893" id="root">
<Library color="#d2ffd0" comment="User defined objects" id="syslib001" name="User"> <Library color="#d2ffd0" comment="User defined objects" id="syslib001" name="User">
<ObjectGroup id="stdid01_1" name="Objects"> <ObjectGroup id="stdid01_1" name="Objects">
<ObjectGroup id="stdid01_1_og_ats_1" name="Address Tables"> <ObjectGroup id="stdid01_1_og_ats_1" name="Address Tables">
@@ -27,6 +27,8 @@
<IPv4 comment="" id="id45D61A0923626" name="VRRP" address="224.0.0.18" netmask="255.255.255.255"/> <IPv4 comment="" id="id45D61A0923626" name="VRRP" address="224.0.0.18" netmask="255.255.255.255"/>
<IPv6 comment="" id="id483426D06131" name="ipv6-1" address="fe80::aaaa:bbbb:cccc:1" netmask="128"/> <IPv6 comment="" id="id483426D06131" name="ipv6-1" address="fe80::aaaa:bbbb:cccc:1" netmask="128"/>
<IPv6 comment="" id="id483426D16131" name="ipv6-2" address="fe80::aaaa:bbbb:cccc:2" netmask="128"/> <IPv6 comment="" id="id483426D16131" name="ipv6-2" address="fe80::aaaa:bbbb:cccc:2" netmask="128"/>
<IPv6 comment="" id="id48416A7116880" name="altavista" address="3ffe:1200:2001:1:8000::1" netmask="128"/>
<IPv6 comment="" id="id48416A7216880" name="6bone.net" address="2001:5c0:0:2::24" netmask="128"/>
</ObjectGroup> </ObjectGroup>
<ObjectGroup id="stdid04_1" name="Groups"> <ObjectGroup id="stdid04_1" name="Groups">
<ObjectGroup id="id3B4572AF" name="group1"> <ObjectGroup id="id3B4572AF" name="group1">
@@ -110,15 +112,15 @@
<ObjectRef ref="id4387287A18346"/> <ObjectRef ref="id4387287A18346"/>
</ObjectGroup> </ObjectGroup>
<ObjectGroup comment="" id="id4834A2238571" name="ipv6 addresses"> <ObjectGroup comment="" id="id4834A2238571" name="ipv6 addresses">
<ObjectRef ref="id483426D06131"/> <ObjectRef ref="id48416A7016880"/>
<ObjectRef ref="id483426D16131"/> <ObjectRef ref="id48416A7216880"/>
<ObjectRef ref="id4834B9206131"/> <ObjectRef ref="id48416A7116880"/>
</ObjectGroup> </ObjectGroup>
<ObjectGroup comment="" id="id4834A2278571" name="ipv4 ipv6 addresses"> <ObjectGroup comment="" id="id4834A2278571" name="ipv4 ipv6 addresses">
<ObjectRef ref="id417B3641"/> <ObjectRef ref="id417B3641"/>
<ObjectRef ref="id483426D06131"/>
<ObjectRef ref="id483426D16131"/>
<ObjectRef ref="id4388C37D674"/> <ObjectRef ref="id4388C37D674"/>
<ObjectRef ref="id48416A7216880"/>
<ObjectRef ref="id48416A7116880"/>
</ObjectGroup> </ObjectGroup>
</ObjectGroup> </ObjectGroup>
<ObjectGroup id="stdid02_1" name="Hosts"> <ObjectGroup id="stdid02_1" name="Hosts">
@@ -831,6 +833,8 @@
<Network comment="" id="id43913DEA25682" name="Internal_net_t" address="192.168.1.0" netmask="255.255.255.0"/> <Network comment="" id="id43913DEA25682" name="Internal_net_t" address="192.168.1.0" netmask="255.255.255.0"/>
<Network comment="" id="id4733FFE419714" name="n-192.168.2.0" address="192.168.2.0" netmask="255.255.255.0"/> <Network comment="" id="id4733FFE419714" name="n-192.168.2.0" address="192.168.2.0" netmask="255.255.255.0"/>
<NetworkIPv6 comment="" id="id4834B9206131" name="net-fe80" address="fe80::" netmask="64"/> <NetworkIPv6 comment="" id="id4834B9206131" name="net-fe80" address="fe80::" netmask="64"/>
<NetworkIPv6 comment="" id="id48416A7016880" name="DIGITAL-CA-DEC" address="3ffe:1200:2000::" netmask="36"/>
<NetworkIPv6 comment="" id="id48416A7316880" name="HEXAGO-V6-NET1" address="2001:5c0::" netmask="32"/>
</ObjectGroup> </ObjectGroup>
<ObjectGroup id="stdid15_1" name="Address Ranges"> <ObjectGroup id="stdid15_1" name="Address Ranges">
<AddressRange comment="" id="id3CD8769F" name="test_range_1" start_address="192.168.1.11" end_address="192.168.1.15"/> <AddressRange comment="" id="id3CD8769F" name="test_range_1" start_address="192.168.1.11" end_address="192.168.1.15"/>
@@ -24365,7 +24369,7 @@ echo '%FWBPROMPT%'; sh /tmp/%FWSCRIPT%
<Option name="verify_interfaces">False</Option> <Option name="verify_interfaces">False</Option>
</FirewallOptions> </FirewallOptions>
</Firewall> </Firewall>
<Firewall comment="" host_OS="linux24" id="id4833F62B6131" inactive="False" lastCompiled="1211586650" lastInstalled="0" lastModified="1212115906" name="firewall-ipv6-1" platform="iptables" ro="False" version=""> <Firewall comment="" host_OS="linux24" id="id4833F62B6131" inactive="False" lastCompiled="1212115999" lastInstalled="0" lastModified="1212118783" name="firewall-ipv6-1" platform="iptables" ro="False" version="">
<NAT id="id4833F62F6131" name="NAT"/> <NAT id="id4833F62F6131" name="NAT"/>
<Policy id="id483F5B7623190" name="Policy_ipv4"/> <Policy id="id483F5B7623190" name="Policy_ipv4"/>
<Policy id="id4833F62E6131" name="Policy"> <Policy id="id4833F62E6131" name="Policy">
@@ -24391,7 +24395,7 @@ echo '%FWBPROMPT%'; sh /tmp/%FWSCRIPT%
</PolicyRule> </PolicyRule>
<PolicyRule action="Accept" comment="" direction="Both" disabled="False" id="id4834578B6131" log="False" position="1"> <PolicyRule action="Accept" comment="" direction="Both" disabled="False" id="id4834578B6131" log="False" position="1">
<Src neg="False"> <Src neg="False">
<ObjectRef ref="id483426D06131"/> <ObjectRef ref="id48416A7216880"/>
</Src> </Src>
<Dst neg="False"> <Dst neg="False">
<ObjectRef ref="id4833F6316131"/> <ObjectRef ref="id4833F6316131"/>
@@ -24411,7 +24415,7 @@ echo '%FWBPROMPT%'; sh /tmp/%FWSCRIPT%
</PolicyRule> </PolicyRule>
<PolicyRule action="Accept" direction="Both" disabled="False" id="id4834577C6131" log="True" position="2"> <PolicyRule action="Accept" direction="Both" disabled="False" id="id4834577C6131" log="True" position="2">
<Src neg="False"> <Src neg="False">
<ObjectRef ref="id483426D06131"/> <ObjectRef ref="id48416A7116880"/>
</Src> </Src>
<Dst neg="False"> <Dst neg="False">
<ObjectRef ref="id4833F62B6131"/> <ObjectRef ref="id4833F62B6131"/>
File diff suppressed because it is too large Load Diff