/*
 * This method builds and returns activation command
 * This method is used for all firewall platforms but PIX
 */
QString FirewallInstaller::getActivationCmd()
{
    if (!cnf->activationCmd.isEmpty())
    {
        return cnf->activationCmd;
    }

    FWOptions *fwopt = cnf->fwobj->getOptionsObject();

    QString configlet_name = "installer_commands_";
    if (cnf->user=="root") configlet_name += "root";
    else                   configlet_name += "reg_user";

    string host_os = cnf->fwobj->getStr("host_OS");
    string os_family = Resources::os_res[host_os]->
        getResourceStr("/FWBuilderResources/Target/family");

    // installer configlets should be different for each OS, but if
    // some OS can use the same script, it will be placed in the file
    // under os_family name. For example:
    // for linksys/sveasoft configlet is in src/res/configlets/sveasoft
    // but since linux24 and openwrt can use the same script, it is
    // located in src/res/configlets/linux24 (openwrt.xml file defines
    // family as "linux24")
    Configlet configlet(host_os, os_family, configlet_name);
    configlet.removeComments();
    configlet.collapseEmptyStrings(true);

    // test run and rollback were deprecated in 4.2.0. On Linux, BSD
    // and PIX rollback was implemented by rebooting firewall which is
    // too heavy-handed and it did not work on BSD at all.
    configlet.setVariable("test", false);
    configlet.setVariable("run", true);
    configlet.setVariable("with_rollback", false);
    configlet.setVariable("no_rollback", true);

    configlet.setVariable("firewall_name",
                          QString::fromUtf8(cnf->fwobj->getName().c_str()));

    configlet.setVariable("with_compression",  cnf->compressScript);
    configlet.setVariable("no_compression",  ! cnf->compressScript);

    // On FreeBSD where we can generate either shell script or rc.conf
    // file, installation commands differ.
    //
    // TODO: find more generic way to do this so that GUI installer does not
    // have to be aware of the differences in generated file format.
    configlet.setVariable("rc_conf_format",
                          fwopt->getBool("generate_rc_conf_file"));
    configlet.setVariable("shell_script_format",
                          ! fwopt->getBool("generate_rc_conf_file"));

    replaceMacrosInCommand(&configlet);

    return configlet.expand().trimmed();
}
void NATCompiler_pf::PrintRule::_printNATRuleOptions(Rule *rule)
{
    FWOptions *ruleopt =rule->getOptionsObject();

    if (ruleopt->getBool("pf_bitmask"))     compiler->output << "bitmask ";
    if (ruleopt->getBool("pf_random"))      compiler->output << "random ";
    if (ruleopt->getBool("pf_source_hash")) compiler->output << "source-hash ";
    if (ruleopt->getBool("pf_round_robin")) compiler->output << "round-robin ";

    if (ruleopt->getBool("pf_static_port")) compiler->output << "static-port ";
}
예제 #3
0
void AutomaticRules_nxosacl::addSshAccessRule()
{
    if (ruleset == NULL) return;

    FWOptions *fwopt = fw->getOptionsObject();

    if (fwopt->getBool("mgmt_ssh") && ! fwopt->getStr("mgmt_addr").empty())
    {
        AutomaticRules_cisco::addSshAccessRule();

        /*
         * AutomaticRules_cisco::addDefaultPolicyRule() adds a rule to
         * permit backup ssh access to the firewall. Since NXOS ACL are
         * stateless, we need to add another rule to permit reply
         * packets.
         */
        TCPService *ssh_rev = ruleset->getRoot()->createTCPService();
        ssh_rev->setSrcRangeStart(22);
        ssh_rev->setSrcRangeEnd(22);
        persistent_objects->add(ssh_rev, false);

        Network *mgmt_workstation = ruleset->getRoot()->createNetwork();
        mgmt_workstation->setAddressNetmask(fwopt->getStr("mgmt_addr"));

        persistent_objects->add(mgmt_workstation, false);

        addMgmtRule(
            fw, mgmt_workstation, ssh_rev,
            NULL, PolicyRule::Outbound, PolicyRule::Accept,
            "backup ssh access rule (out)");
    }
}
/*
 * Generate calls to the shell function update_addresses_of_interface
 * to add or remove ip addresses of interfaces. The following cases
 * are supported, depending on the value of
 * @add_virtual_addresses_for_nat and @configure_interfaces
 *
 * configure_interfaces == false && add_virtual_addresses_for_nat == false:  
 *   do not generate any commands
 *
 * configure_interfaces == false && add_virtual_addresses_for_nat == true:  
 *   use only  virtual_addresses_for_nat, add normal addresses of the interface
 *   to the list of addresses we should ignore
 * 
 * configure_interfaces == true && add_virtual_addresses_for_nat == false:
 *   ignore  virtual_addresses_for_nat
 * 
 * configure_interfaces == true && add_virtual_addresses_for_nat == true:
 *   use  virtual_addresses_for_nat
 * 
 * 
 */
string OSConfigurator_linux24::printInterfaceConfigurationCommands()
{
    FWOptions* options = fw->getOptionsObject();

    std::unique_ptr<interfaceProperties> int_prop(
        interfacePropertiesObjectFactory::getInterfacePropertiesObject(
            fw->getStr("host_OS")));

    Configlet script(fw, "linux24", "configure_interfaces");
    script.removeComments();
    script.collapseEmptyStrings(true);

    list<FWObject*> interfaces = fw->getByTypeDeep(Interface::TYPENAME);
    bool need_promote_command = false;
    QStringList gencmd;
    list<FWObject*>::iterator i;
    for (i=interfaces.begin(); i!=interfaces.end(); ++i )
    {
        Interface *iface = Interface::cast(*i);
        assert(iface);
        string iface_name = iface->getName();

        QStringList update_addresses;
        QStringList ignore_addresses;

        if (int_prop->manageIpAddresses(iface, update_addresses, ignore_addresses))
        {
            if (options->getBool("manage_virtual_addr") &&
                virtual_addresses_for_nat.count(iface_name) > 0)
                update_addresses.push_back(
                    virtual_addresses_for_nat[iface_name].c_str());

            // generate update_addresses calls even if interface has
            // no addresses in fwbuilder. This makes sure all
            // addresses it might have on the machine will be
            // removed. Say, interface was regular and had an address
            // and then user converted it to unnumbered. In this case
            // the address should be removed.

            gencmd.push_back(
                printUpdateAddressCommand(iface, update_addresses, ignore_addresses));

            // update_addresses list looks like this:
            // ("eth0", "22.22.22.22/24", "22.22.22.23/24") 
            // I need to add "promote" command only when there is more than 1 address.
            need_promote_command |= (update_addresses.size() > 2);
        }

        known_interfaces.push_back(iface_name);
    }

    script.setVariable("have_interfaces", interfaces.size() > 0);
    script.setVariable("need_promote_command", need_promote_command);
    script.setVariable("configure_interfaces_script", gencmd.join("\n"));
    return script.expand().toStdString() + "\n";
}
string PolicyCompiler_iosacl::PrintRule::_printLog(PolicyRule *rule)
{
    if (rule->getLogging())
    {
        FWOptions  *ruleopt =rule->getOptionsObject();
        if (ruleopt->getBool("iosacl_log_input")) return "log-input ";
        return "log ";
    }
    return "";
}
bool PolicyCompiler_pf::ProcessScrubOption::processNext()
{
    PolicyRule *rule=getNext(); if (rule==NULL) return false;

    FWOptions *ruleopt =rule->getOptionsObject();


    if ( ruleopt->getBool("scrub") ) {

	if (rule->getAction()!=PolicyRule::Accept) {
	    ruleopt->setBool("scrub",false);
	    tmp_queue.push_back(rule);

	    compiler->abort(rule,
                            "Rule option 'scrub' is supported only for rules "
                            "with action 'Accept'");

	    return true;
	}

	PolicyRule *r = compiler->dbcopy->createPolicyRule();
	compiler->temp_ruleset->add(r);
	r->duplicate(rule);
	r->setAction(PolicyRule::Scrub);
	r->getOptionsObject()->setBool("scrub",false);
	tmp_queue.push_back(r);

	ruleopt->setBool("scrub",false);
	tmp_queue.push_back(rule);

	return true;
    }

/* if service is ip_fragment and action is 'Deny', then add rule with scrub */

    Service *srv=compiler->getFirstSrv(rule);    assert(srv);

    if ( (srv->getBool("short_fragm") || srv->getBool("fragm")) &&
	 ( rule->getAction()==PolicyRule::Deny || rule->getAction()==PolicyRule::Reject) ) {

	PolicyRule *r = compiler->dbcopy->createPolicyRule();
	compiler->temp_ruleset->add(r);
	r->duplicate(rule);
	r->setAction(PolicyRule::Scrub);
	r->getOptionsObject()->setBool("scrub",false);
	tmp_queue.push_back(r);

	return true;
    }

    tmp_queue.push_back(rule);
    return true;
}
예제 #7
0
OSConfigurator_linux24::OSConfigurator_linux24(FWObjectDatabase *_db,
                                               Firewall *fw,
                                               bool ipv6_policy) : 
    OSConfigurator(_db, fw, ipv6_policy) , os_data(fw->getStr("host_OS"))
{
    command_wrappers = new Configlet(fw, "linux24", "run_time_wrappers");

    FWOptions* fwopt = fw->getOptionsObject();
    string version = fw->getStr("version");
    using_ipset = (XMLTools::version_compare(version, "1.4.1.1") >= 0 &&
                          fwopt->getBool("use_m_set"));
}
bool PolicyCompiler_ipf::expandAnyService::processNext()
{
    PolicyCompiler_ipf *pcomp=dynamic_cast<PolicyCompiler_ipf*>(compiler);
    PolicyRule *rule=getNext(); if (rule==NULL) return false;

    RuleElementSrv *srv=rule->getSrv();
    FWOptions *ruleopt =rule->getOptionsObject();

    if (srv->isAny() && ! ruleopt->getBool("stateless") && rule->getAction()==PolicyRule::Accept) {

	PolicyRule *r = compiler->dbcopy->createPolicyRule();
	compiler->temp_ruleset->add(r);
	r->duplicate(rule);
	RuleElementSrv *nsrv=r->getSrv();
	nsrv->clearChildren();
	nsrv->addRef(pcomp->anyicmp); //compiler->dbcopy->findInIndex(ANY_ICMP_OBJ_ID));
	tmp_queue.push_back(r);

	r = compiler->dbcopy->createPolicyRule();
	compiler->temp_ruleset->add(r);
	r->duplicate(rule);
	nsrv=r->getSrv();
	nsrv->clearChildren();
	nsrv->addRef(pcomp->anytcp); //compiler->dbcopy->findInIndex(ANY_TCP_OBJ_ID));
	tmp_queue.push_back(r);

	r = compiler->dbcopy->createPolicyRule();
	compiler->temp_ruleset->add(r);
	r->duplicate(rule);
	nsrv=r->getSrv();
	nsrv->clearChildren();
	nsrv->addRef(pcomp->anyudp); //compiler->dbcopy->findInIndex(ANY_UDP_OBJ_ID));
	tmp_queue.push_back(r);

	r = compiler->dbcopy->createPolicyRule();
	compiler->temp_ruleset->add(r);
	r->duplicate(rule);
	FWOptions *ruleopt =r->getOptionsObject();
	ruleopt->setBool("stateless",true);
	tmp_queue.push_back(r);

    } else
	tmp_queue.push_back(rule);

    return true;
}
예제 #9
0
string OSConfigurator_linux24::generateCodeForProtocolHandlers()
{
    FWOptions* options = fw->getOptionsObject();
    bool nomod = Resources::os_res[fw->getStr("host_OS")]->
        Resources::getResourceBool("/FWBuilderResources/Target/options/suppress_modules");

    // string host_os = fw->getStr("host_OS");
    // string os_family = Resources::os_res[host_os]->
    //     getResourceStr("/FWBuilderResources/Target/family");
    Configlet load_modules(fw, "linux24", "load_modules");
    load_modules.removeComments();

    // See ticket #2
    string modules_dir = Resources::os_res[fw->getStr("host_OS")]->
        Resources::getResourceStr("/FWBuilderResources/Target/options/default/modules_dir");

/* there is no need to load modules on some platforms */
    load_modules.setVariable("load_modules", options->getBool("load_modules") && !nomod);
    load_modules.setVariable("modules_dir", modules_dir.c_str());
    return load_modules.expand().toStdString();
}
예제 #10
0
string OSConfigurator_bsd::printFunctions()
{
    ostringstream ostr;

    FWOptions* options = fw->getOptionsObject();
    string host_os = fw->getStr("host_OS");
    string version = fw->getStr("version");

    Configlet functions(fw, "bsd", "shell_functions");
    functions.removeComments();
    functions.setVariable("dyn_addr", options->getBool("dynAddr"));

    if (options->getBool("dynAddr"))
    {
/*
 * get addresses of dynamic interfaces
 */
        QString script_buffer;
        QTextStream ostr(&script_buffer, QIODevice::WriteOnly);
        FWObjectTypedChildIterator j=fw->findByType(Interface::TYPENAME);
        for ( ; j!=j.end(); ++j ) 
        {
            Interface *iface=Interface::cast(*j);
        
            if ( iface->isDyn() )
            {
/* if interface name ends with '*', this is a wildcard interface. Do
 * not get its address at this time. 
 *
 * Do we support wildcard interfaces on *BSD at all ?
 */
                if (iface->getName().find("*")==string::npos)
                    ostr << "getaddr "
                         << iface->getName().c_str()
                         << "  "
                         << getInterfaceVarName(iface).c_str()
                         << "\n";
            }
        }
        functions.setVariable("get_dyn_addr_commands", script_buffer);
    } else
        functions.setVariable("get_dyn_addr_commands", "");

    ostr << functions.expand().toStdString();

    if ( options->getBool("configure_interfaces") ) 
    {
        Configlet update_addresses(fw, "bsd", "update_addresses");
        update_addresses.removeComments();
        update_addresses.setVariable("freebsd", host_os == "freebsd");
        update_addresses.setVariable("openbsd", host_os == "openbsd");
        ostr << update_addresses.expand().toStdString();
    }

    if ( options->getBool("configure_vlan_interfaces") ) 
    {
        Configlet update_vlans(fw, "bsd", "update_vlans");
        update_vlans.removeComments();
        update_vlans.setVariable("freebsd", host_os == "freebsd");
        update_vlans.setVariable("openbsd", host_os == "openbsd");
        ostr << update_vlans.expand().toStdString();
    }

    if (options->getBool("configure_bridge_interfaces"))
    {
        Configlet update_bridge(fw, "bsd", "update_bridge");
        update_bridge.removeComments();
        update_bridge.setVariable("freebsd", host_os == "freebsd");
        if (host_os == "openbsd")
        {
            update_bridge.setVariable("openbsd", true);
            update_bridge.setVariable("openbsd_lt_47",
                                      XMLTools::version_compare(version, "4.7")<0);
            update_bridge.setVariable("openbsd_ge_47",
                                      XMLTools::version_compare(version, "4.7")>=0);
        }

        ostr << update_bridge.expand().toStdString();
    }

    if ( options->getBool("configure_carp_interfaces") ) 
    {
        Configlet update_carp(fw, "bsd", "update_carp");
        update_carp.removeComments();
        update_carp.setVariable("freebsd", host_os == "freebsd");
        update_carp.setVariable("openbsd", host_os == "openbsd");
        ostr << update_carp.expand().toStdString();
    }

    if ( options->getBool("configure_pfsync_interfaces") ) 
    {
        Configlet update_pfsync(fw, "bsd", "update_pfsync");
        update_pfsync.removeComments();
        update_pfsync.setVariable("freebsd", host_os == "freebsd");
        update_pfsync.setVariable("openbsd", host_os == "openbsd");
        ostr << update_pfsync.expand().toStdString();
    }

    return ostr.str();
}
bool MangleTableCompiler_ipt::keepMangleTableRules::processNext()
{
    PolicyRule *rule = getNext(); if (rule==NULL) return false;
    FWOptions *ruleopt = rule->getOptionsObject();
    PolicyCompiler_ipt *ipt_comp = dynamic_cast<PolicyCompiler_ipt*>(compiler);

    string ruleset_name = compiler->getRuleSetName();

    FWOptions *rulesetopts = ipt_comp->getSourceRuleSet()->getOptionsObject();
    if (rulesetopts->getBool("mangle_only_rule_set"))
        tmp_queue.push_back(rule);
    else
    {
        if (rule->getAction() == PolicyRule::Branch &&
            ruleopt->getBool("ipt_branch_in_mangle"))
        {
            PolicyRule* r;
        
            // this is a branching rule for mangle table. Need to put it
            // into PREROUTING and POSTROUTING chains as well because some
            // targets that work with mangle table can only go into these
            // chains, yet we do not know what kind of rules will user
            // place in the branch

            if (rule->getDirection()==PolicyRule::Undefined ||
                rule->getDirection()==PolicyRule::Both ||
                rule->getDirection()==PolicyRule::Inbound)
            {
                r= compiler->dbcopy->createPolicyRule();
                compiler->temp_ruleset->add(r);
                r->duplicate(rule);
                r->setStr("ipt_chain","PREROUTING");
                tmp_queue.push_back(r);
            }

            if (rule->getDirection()==PolicyRule::Undefined ||
                rule->getDirection()==PolicyRule::Both ||
                rule->getDirection()==PolicyRule::Outbound)
            {
                r= compiler->dbcopy->createPolicyRule();
                compiler->temp_ruleset->add(r);
                r->duplicate(rule);
                r->setStr("ipt_chain","POSTROUTING");
                tmp_queue.push_back(r);
            }

            // ticket #1415 User reports that only packets that went
            // through the FORWARD chain can match inbound "-i" and
            // outbound "-o" interface at the same time. Since we do
            // not allow both in and out interface matches in one rule
            // and have to use branch to do this, need to branch in
            // FORWARD chain as well so that inbound interface can be
            // matched in the branching rule and outbound interface
            // can be matched in a rule in the branch
            //
            // This is ugly, this means the branch will inspect the
            // packet at least twice - in PREROUTING and FORWARD, or
            // FORWARD and POSTROUTING chains.
            //
            // I mention above that some targets can only be used in
            // PREROUTING or POSTROUTING chains. It would help if
            // these tagrets worked in FORWARD chain, in that case we
            // could just branch in FORWARD instead of all thress chains.
            //
            r= compiler->dbcopy->createPolicyRule();
            compiler->temp_ruleset->add(r);
            r->duplicate(rule);
            r->setStr("ipt_chain","FORWARD");
            tmp_queue.push_back(r);

            // tmp_queue.push_back(rule);
            return true;
        }

        if (rule->getTagging() ||
            rule->getRouting() ||
            rule->getClassification() ||
            ruleopt->getBool("put_in_mangle_table")) tmp_queue.push_back(rule);
    }

    return true;
}
예제 #12
0
QString CompilerDriver_pix::run(const std::string &cluster_id,
                                const std::string &firewall_id,
                                const std::string &single_rule_id)
{
    Cluster *cluster = NULL;
    Firewall *fw = NULL;

    getFirewallAndClusterObjects(cluster_id, firewall_id, &cluster, &fw);

    // Copy rules from the cluster object
    populateClusterElements(cluster, fw);

    if (cluster)
    {
        // PIX failover is dfferent from VRRP and other failover protocols
        // in that it does not create new virtual address. Instead, each
        // unit is configured with two ip addresses, one for the active
        // unit and another for standby one. When active unit fails, the
        // other one assumes its address.
        //
        // This matters because when we use cluster object or one of its
        // interfaces in rules, compiler should expand it to the set of
        // addresses that includes addresses of the corresponding
        // interface of both member firewalls. Method
        // CompilerDriver::copyFailoverInterface adds a copy of firewall
        // interface to the cluster object. This works for all firewalls,
        // but for PIX we need to add copies of interfaces from both
        // members.
        // 
        FWObjectTypedChildIterator cl_iface = cluster->findByType(Interface::TYPENAME);
        for (; cl_iface != cl_iface.end(); ++cl_iface)
        {
            FailoverClusterGroup *failover_group =
                FailoverClusterGroup::cast(
                    (*cl_iface)->getFirstByType(FailoverClusterGroup::TYPENAME));
            if (failover_group)
            {
                //FWObject *this_member_interface = NULL; //UNUSED
                list<FWObject*> other_member_interfaces;
                for (FWObjectTypedChildIterator it =
                         failover_group->findByType(FWObjectReference::TYPENAME);
                     it != it.end(); ++it)
                {
                    FWObject *intf = FWObjectReference::getObject(*it);
                    assert(intf);
                    //if (intf->isChildOf(fw)) this_member_interface = intf; //UNUSED
                    //else other_member_interfaces.push_back(intf);
                    if (!intf->isChildOf(fw)) other_member_interfaces.push_back(intf);
                }

                if (!other_member_interfaces.empty())
                {
                    for (list<FWObject*>::iterator it=other_member_interfaces.begin();
                         it!=other_member_interfaces.end(); ++it)
                    {
                        cluster->addCopyOf(*it, true);
                    }
                }
            }
        }
    }

#if 0
    FWObjectTypedChildIterator iface = fw->findByType(Interface::TYPENAME);
    for (; iface != iface.end(); ++iface)
    {
        (*iface)->dump(true, true);
    }
#endif


    determineOutputFileNames(cluster, fw, !cluster_id.empty(),
                             QStringList(""), QStringList("fw"),
                             QStringList(""));

    FWOptions* options = fw->getOptionsObject();

    QString script_buffer;

    std::auto_ptr<NATCompiler_pix> n;
    std::auto_ptr<PolicyCompiler_pix> c;
    std::auto_ptr<RoutingCompiler_pix> r;


    try
    {
        clearReadOnly(fw);

        commonChecks2(cluster, fw);

        pixClusterConfigurationChecks(cluster, fw);

        // Note that fwobjectname may be different from the name of the
        // firewall fw This happens when we compile a member of a cluster
        current_firewall_name = fw->getName().c_str();

        bool pix_acl_basic = options->getBool("pix_acl_basic");
        bool pix_acl_no_clear = options->getBool("pix_acl_no_clear");
        bool pix_acl_substitution = options->getBool("pix_acl_substitution");
        bool pix_add_clear_statements = options->getBool("pix_add_clear_statements");

        if (!pix_acl_basic && !pix_acl_no_clear && !pix_acl_substitution)
        {
            if ( pix_add_clear_statements ) options->setBool("pix_acl_basic",true);
            else options->setBool("pix_acl_no_clear",true);
        }



        list<FWObject*> all_interfaces = fw->getByTypeDeep(Interface::TYPENAME);

        pixSecurityLevelChecks(fw, all_interfaces);
        pixNetworkZoneChecks(fw, all_interfaces);

        /* Now that all checks are done, we can drop copies of cluster
         * interfaces that were added to the firewall by
         * CompilerDriver::populateClusterElements()
         */
        list<FWObject*> copies_of_cluster_interfaces;
        for (std::list<FWObject*>::iterator i=all_interfaces.begin(); i!=all_interfaces.end(); ++i)
        {
            Interface *iface = Interface::cast(*i);
            assert(iface);

            if (iface->getOptionsObject()->getBool("cluster_interface"))
                copies_of_cluster_interfaces.push_back(iface);
        }
        while (copies_of_cluster_interfaces.size())
        {
            fw->remove(copies_of_cluster_interfaces.front());
            copies_of_cluster_interfaces.pop_front();
        }

        NamedObjectsManagerPIX named_objects_manager(persistent_objects, fw);

        all_interfaces = fw->getByTypeDeep(Interface::TYPENAME);

        for (std::list<FWObject*>::iterator i=all_interfaces.begin();
             i!=all_interfaces.end(); ++i)
        {
            Interface *iface = Interface::cast(*i);
            assert(iface);
/*
 * missing labels on interfaces
 *
 */
            if (iface->getLabel()=="")
            {
                string lbl;
                if (iface->isDedicatedFailover()) 
                {
                    // dedicated failover interface misses label. This
                    // interface can be used in failover cluster group
                    // or state sync group. Assign label depending on
                    // the function.
                    FWObjectTypedChildIterator it =
                        cluster->findByType(StateSyncClusterGroup::TYPENAME);
                    StateSyncClusterGroup *state_sync_group =
                        StateSyncClusterGroup::cast(*it);
                    if (state_sync_group && state_sync_group->hasMember(iface))
                        lbl = "state";

                    if (!iface->getOptionsObject()->getStr("failover_group_id").empty())
                        lbl = "failover";
                }

                if (lbl.empty())
                {
                    if (iface->getSecurityLevel()==0)   lbl="outside";
                    else
                    {
                        if (iface->getSecurityLevel()==100) lbl="inside";
                        else
                        {
                            QString l("dmz%1");
                            lbl = l.arg(iface->getSecurityLevel()).toStdString();
                        }
                    }
                }
                iface->setLabel(lbl);
            }



        }
        /*
         *  now sort interfaces by their network zone "width" (that
         *  is, more narrow network zone should go first, interface
         *  with network zone "any" should be the last)
         *
         std::sort(fw->begin(), fw->end(), sort_by_net_zone() );
        */


        try
        {
            AutomaticRules_cisco auto_rules(fw, persistent_objects);
            auto_rules.addSshAccessRule();
        } catch (FWException &ex)
        {
            abort(ex.toString());
        }

        std::auto_ptr<Preprocessor> prep(
            new Preprocessor(objdb , fw, false));
        if (inTestMode()) prep->setTestMode();
        if (inEmbeddedMode()) prep->setEmbeddedMode();
        prep->compile();

        std::auto_ptr<OSConfigurator> oscnf(
            new OSConfigurator_pix_os(objdb , fw, false));
        if (inTestMode()) oscnf->setTestMode();
        if (inEmbeddedMode()) oscnf->setEmbeddedMode();

        oscnf->prolog();
        oscnf->processFirewallOptions();

        bool have_named_objects = false;
        bool have_object_groups = false;

/* create compilers and run the whole thing */
        string version = fw->getStr("version");

        if (XMLTools::version_compare(version, "8.3")>=0)
            n = std::auto_ptr<NATCompiler_pix>(
                new NATCompiler_asa8(objdb, fw, false, oscnf.get()));
        else
            n = std::auto_ptr<NATCompiler_pix>(
                new NATCompiler_pix(objdb, fw, false, oscnf.get()));

        RuleSet *nat = RuleSet::cast(fw->getFirstByType(NAT::TYPENAME));
        if (nat)
        {
            nat->assignUniqueRuleIds();

            n->setNamedObjectsManager(&named_objects_manager);
            n->setSourceRuleSet(nat);
            n->setRuleSetName(nat->getName());
            n->setPersistentObjects(persistent_objects);

            if (inTestMode()) n->setTestMode();
            if (inEmbeddedMode()) n->setEmbeddedMode();
            n->setSingleRuleCompileMode(single_rule_id);
            n->setDebugLevel( dl );
            if (rule_debug_on) n->setDebugRule(  drn );
            n->setVerbose( verbose );

            if ( n->prolog() > 0 )
            {
                n->compile();
                n->epilog();

                preamble_commands += n->printPreambleCommands();
                clear_commands += n->printClearCommands();
                have_named_objects = (have_named_objects ||
                                      named_objects_manager.haveNamedObjects());
                have_object_groups = (have_object_groups ||
                                      named_objects_manager.haveObjectGroups());
                //named_objects_manager.saveObjectGroups();
            } else
                info(" Nothing to compile in NAT");
        }

        c = std::auto_ptr<PolicyCompiler_pix>(
            new PolicyCompiler_pix(objdb, fw, false, oscnf.get() , n.get()));

        RuleSet *policy = RuleSet::cast(fw->getFirstByType(Policy::TYPENAME));
        if (policy)
        {
            policy->assignUniqueRuleIds();

            c->setNamedObjectsManager(&named_objects_manager);
            c->setSourceRuleSet(policy);
            c->setRuleSetName(policy->getName());
            c->setPersistentObjects(persistent_objects);

            if (inTestMode()) c->setTestMode();
            if (inEmbeddedMode()) c->setEmbeddedMode();
            c->setSingleRuleCompileMode(single_rule_id);
            c->setDebugLevel( dl );
            if (rule_debug_on) c->setDebugRule(  drp );
            c->setVerbose( verbose );

            if ( c->prolog() > 0 )
            {
                c->compile();
                c->epilog();

                preamble_commands += c->printPreambleCommands();
                clear_commands += c->printClearCommands();
                have_named_objects = (have_named_objects ||
                                      named_objects_manager.haveNamedObjects());
                have_object_groups = (have_object_groups ||
                                      named_objects_manager.haveObjectGroups());
                //named_objects_manager.saveObjectGroups();
            } else
                info(" Nothing to compile in Policy");
        }

        r = std::auto_ptr<RoutingCompiler_pix>(
            new RoutingCompiler_pix(objdb, fw, false, oscnf.get()));

        RuleSet *routing = RuleSet::cast(fw->getFirstByType(Routing::TYPENAME));
        if (routing)
        {
            routing->assignUniqueRuleIds();

            r->setNamedObjectsManager(&named_objects_manager);
            r->setSourceRuleSet(routing);
            r->setRuleSetName(routing->getName());
            r->setPersistentObjects(persistent_objects);
                
            if (inTestMode()) r->setTestMode();
            if (inEmbeddedMode()) r->setEmbeddedMode();
            r->setSingleRuleCompileMode(single_rule_id);
            r->setDebugLevel( dl );
            if (rule_debug_on) r->setDebugRule(  drp );
            r->setVerbose( verbose );

            if ( r->prolog() > 0 )
            {
                r->compile();
                r->epilog();
            } else
                info(" Nothing to compile in Routing");
        }

        /*
         * compilers detach persistent objects when they finish, this
         * means at this point library persistent_objects is not part
         * of any object tree.
         */
        objdb->reparent(persistent_objects);

        if (haveErrorsAndWarnings())
        {
            all_errors.push_front(getErrors("").c_str());
        }

        policy_script = c->getCompiledScript();
        nat_script = n->getCompiledScript();
        routing_script = r->getCompiledScript();

        named_objects_and_groups = named_objects_manager.getNamedObjectsDefinitions();

        if (c->haveErrorsAndWarnings())
            all_errors.push_back(c->getErrors("C ").c_str());
        if (n->haveErrorsAndWarnings())
            all_errors.push_back(n->getErrors("N ").c_str());
        if (r->haveErrorsAndWarnings())
            all_errors.push_back(r->getErrors("R ").c_str());

        if (single_rule_compile_on)
        {
            return formSingleRuleCompileOutput(
                QString::fromUtf8(
                    (named_objects_and_groups +
                     policy_script + nat_script + routing_script).c_str()));
        }

        system_configuration_script = oscnf->getCompiledScript();
        system_configuration_script += "\n";

        clear_commands += named_objects_manager.getClearCommands() + "\n";

        // system_configuration_script += preamble_commands;
        // system_configuration_script += clear_commands;


        script_buffer = assembleFwScript(
            cluster, fw, !cluster_id.empty(), oscnf.get());

        QString ofname = getAbsOutputFileName(file_names[FW_FILE]);

        info("Output file name: " + ofname.toStdString());
        QFile fw_file(ofname);
        if (fw_file.open(QIODevice::WriteOnly))
        {
            QTextStream fw_str(&fw_file);
            fw_str << script_buffer;
            fw_file.close();
            fw_file.setPermissions(QFile::ReadOwner | QFile::WriteOwner |
                                   QFile::ReadGroup | QFile::ReadOther |
                                   QFile::ExeOwner | 
                                   QFile::ExeGroup |
                                   QFile::ExeOther );

            info(" Compiled successfully");
        } else
        {
            QString err(" Failed to open file %1 for writing: %2; Current dir: %3");
            abort(err.arg(fw_file.fileName())
                  .arg(fw_file.error()).arg(QDir::current().path()).toStdString());
        }

        if (!all_errors.isEmpty())
            status = BaseCompiler::FWCOMPILER_WARNING;

    }
    catch (FWException &ex)
    {
        status = BaseCompiler::FWCOMPILER_ERROR;
        return QString::fromUtf8(ex.toString().c_str());
    }

    return "";
}
예제 #13
0
QString CompilerDriver_pix::assembleFwScript(Cluster *cluster,
                                             Firewall* fw,
                                             bool cluster_member,
                                             OSConfigurator *oscnf)
{
    Configlet script_skeleton(fw, "pix_os", "script_skeleton");
    Configlet top_comment(fw, "pix_os", "top_comment");

    FWOptions* options = fw->getOptionsObject();
    options->setStr("prolog_script", options->getStr("pix_prolog_script"));
    options->setStr("epilog_script", options->getStr("pix_epilog_script"));
    options->setStr("prolog_place", "");

    string vers = fw->getStr("version");
    string platform = fw->getStr("platform");

    bool outbound_acl_supported =
        Resources::platform_res[platform]->getResourceBool(
            string("/FWBuilderResources/Target/options/")+
            "version_"+vers+
            "/pix_outbound_acl_supported");

    bool afpa = options->getBool("pix_assume_fw_part_of_any");
    bool emulate_outb_acls = options->getBool("pix_emulate_out_acl");
    bool generate_outb_acls = options->getBool("pix_generate_out_acl");

    top_comment.setVariable(
        "outbound_acl_supported",
        QString((outbound_acl_supported) ? "supported" : "not supported"));

    top_comment.setVariable("emulate_outb_acls",
                            QString((emulate_outb_acls)?"yes":"no"));

    top_comment.setVariable("generate_outb_acls",
                            QString((generate_outb_acls)?"yes":"no"));

    top_comment.setVariable("afpa", QString((afpa)?"yes":"no"));

    script_skeleton.setVariable("short_script", options->getBool("short_script"));

    script_skeleton.setVariable("not_short_script",
                                ! options->getBool("short_script"));

    script_skeleton.setVariable("preamble_commands", 
                                QString::fromUtf8(
                                    preamble_commands.c_str()));

    script_skeleton.setVariable("clear_commands", 
                                QString::fromUtf8(
                                    clear_commands.c_str()));

    script_skeleton.setVariable("system_configuration_script", 
                                QString::fromUtf8(
                                    system_configuration_script.c_str()));

    script_skeleton.setVariable("named_objects_and_object_groups",
                                QString::fromUtf8(
                                    named_objects_and_groups.c_str()));

    script_skeleton.setVariable("policy_script",
                                QString::fromUtf8(policy_script.c_str()));
    script_skeleton.setVariable("nat_script",
                                QString::fromUtf8(nat_script.c_str()));
    script_skeleton.setVariable("routing_script",
                                QString::fromUtf8(routing_script.c_str()));

    assembleFwScriptInternal(cluster, fw, cluster_member, oscnf,
                             &script_skeleton, &top_comment, "!", true);

    return script_skeleton.expand();
}
예제 #14
0
/*
 * Go through paces to compile firewall which may be a member of a
 * cluster.  Note that both firewall and cluster are defined by their
 * unique string IDs.  This is necessary because CompilerDriver
 * operates with a copy of the object database which is not exposed
 * outside, so the caller can not provide pointers to these obejcts.
 */
QString CompilerDriver_ipt::run(const std::string &cluster_id,
                                const std::string &firewall_id,
                                const std::string &single_rule_id)
{

    FWObjectDatabase::registerObjectType(combinedAddress::TYPENAME,
                                         &create_combinedAddress);

    // see #2212 Create temporary copy of the firewall and cluster
    // objects and pass them to the compilers.

    Cluster *cluster = NULL;
    Firewall *fw = NULL;

    getFirewallAndClusterObjects(cluster_id, firewall_id, &cluster, &fw);

    string generated_script;

    try
    {
        clearReadOnly(fw);

        // Copy rules from the cluster object
        populateClusterElements(cluster, fw);

        commonChecks2(cluster, fw);

        string fw_version = fw->getStr("version");
        if (fw_version.empty()) fw_version = "(any version)";
        string platform = fw->getStr("platform");
        string host_os = fw->getStr("host_OS");

        FWOptions* options = fw->getOptionsObject();
        string s;

        // Note that fwobjectname may be different from the name of the
        // firewall fw This happens when we compile a member of a cluster
        current_firewall_name = fw->getName().c_str();

        if (fw->getOptionsObject()->getStr("prolog_place") == "after_flush" &&
            fw->getOptionsObject()->getBool("use_iptables_restore"))
        {
            abort("Prolog place \"after policy reset\" can not be used"
                  " when policy is activated with iptables-restore");
        }

        string firewall_dir = options->getStr("firewall_dir");
        if (firewall_dir=="") firewall_dir="/etc";

        bool debug=options->getBool("debug");
        QString shell_dbg = (debug)?"set -x":"" ;

        std::auto_ptr<OSConfigurator_linux24> oscnf;

        string platform_family = Resources::platform_res[platform]->
            getResourceStr("/FWBuilderResources/Target/family");
        string os_family = Resources::os_res[host_os]->
            getResourceStr("/FWBuilderResources/Target/family");

        bool supports_prolog_epilog = Resources::getTargetCapabilityBool(
            platform, "supports_prolog_epilog");

        if (!supports_prolog_epilog)
        {
            prolog_done = true;
            epilog_done = true;
        }

        string os_variant = DISTRO;

/* minimal sanity checking */
        if (os_family == "ipcop")
        {
            os_variant = "ipcop";

            // can't use iptables-restore with ipcop
            fw->getOptionsObject()->setBool("use_iptables_restore", false);
            // ipcop has its own iptables commands that accept packets
            // in states ESTABLISHED,RELATED
            fw->getOptionsObject()->setBool("accept_established", false);

            oscnf = std::auto_ptr<OSConfigurator_linux24>(
                new OSConfigurator_ipcop(objdb , fw, false));
        }

        if (os_family == "linux24" ||
            os_family == "openwrt" ||
            os_family == "dd-wrt-nvram" ||
            os_family == "dd-wrt-jffs" ||
            os_family == "sveasoft")
            oscnf = std::auto_ptr<OSConfigurator_linux24>(
                new OSConfigurator_linux24(objdb , fw, false));

        if (os_family == "secuwall")
            oscnf = std::auto_ptr<OSConfigurator_linux24>(
                new OSConfigurator_secuwall(objdb , fw, false));

        if (oscnf.get()==NULL)
        {
            abort("Unrecognized host OS " + fw->getStr("host_OS") +
                  "  (family " + os_family+")");
            return "";
        }

        if (inTestMode()) oscnf->setTestMode();
        if (inEmbeddedMode()) oscnf->setEmbeddedMode();

        oscnf->validateInterfaces();
        oscnf->prolog();

        list<FWObject*> all_policies = fw->getByType(Policy::TYPENAME);
        list<FWObject*> all_nat = fw->getByType(NAT::TYPENAME);

        int routing_rules_count = 0;
        bool have_ipv4 = false;
        bool have_ipv6 = false;

        // track chains in each table separately. Can we have the same
        // chain in filter and mangle tables ? Would it be the same
        // chain, i.e. do we need to create it only once or do we create
        // it twice, in each table separately ? 
        // Using separate trackers we track and create chain in each
        // table separately.
        std::map<const std::string, bool> minus_n_commands_filter;
        std::map<const std::string, bool> minus_n_commands_mangle;
        std::map<const std::string, bool> minus_n_commands_nat;

        vector<int> ipv4_6_runs;

        findImportedRuleSets(fw, all_policies);
        findBranchesInMangleTable(fw, all_policies);
        findImportedRuleSets(fw, all_nat);

        try
        {
            AutomaticRules_ipt auto_rules(fw, persistent_objects);
            auto_rules.addConntrackRule();
            auto_rules.addFailoverRules();
        } catch (FWException &ex)
        {
            abort(ex.toString());
        }

        // assign unique rule ids that later will be used to generate
        // chain names.  This should be done after calls to
        // findImportedRuleSets()

        assignUniqueRuleIds(all_policies);
        assignUniqueRuleIds(all_nat);

        // command line options -4 and -6 control address family for which
        // script will be generated. If "-4" is used, only ipv4 part will 
        // be generated. If "-6" is used, only ipv6 part will be generated.
        // If neither is used, both parts will be done.

        if (options->getStr("ipv4_6_order").empty() ||
            options->getStr("ipv4_6_order") == "ipv4_first")
        {
            if (ipv4_run) ipv4_6_runs.push_back(AF_INET);
            if (ipv6_run) ipv4_6_runs.push_back(AF_INET6);
        }

        if (options->getStr("ipv4_6_order") == "ipv6_first")
        {
            if (ipv6_run) ipv4_6_runs.push_back(AF_INET6);
            if (ipv4_run) ipv4_6_runs.push_back(AF_INET);
        }

        for (vector<int>::iterator i=ipv4_6_runs.begin(); i!=ipv4_6_runs.end(); ++i)
        {
            int policy_af = *i;
            bool ipv6_policy = (policy_af == AF_INET6);

            /*
              clear chain tracker map only between ipv4/ipv6 runs
              Don't clear it between compiler runs for different
              policy or nat objects for the same address family.
            */
            minus_n_commands_filter.clear();
            minus_n_commands_mangle.clear();
            minus_n_commands_nat.clear();

            /*
              We need to create and run preprocessor for this address
              family before nat and policy compilers, but if there are
              no nat / policy rules for this address family, we do not
              need preprocessor either.
            */

            // Count rules for each address family
            int nat_count = 0;
            int policy_count = 0;

            for (list<FWObject*>::iterator p=all_nat.begin();
                 p!=all_nat.end(); ++p)
            {
                NAT *nat = NAT::cast(*p);
                if (nat->matchingAddressFamily(policy_af)) nat_count++;
            }

            for (list<FWObject*>::iterator p=all_policies.begin();
                 p!=all_policies.end(); ++p)
            {
                Policy *policy = Policy::cast(*p);
                if (policy->matchingAddressFamily(policy_af)) policy_count++;
            }

            if (nat_count || policy_count)
            {
                Preprocessor_ipt* prep = new Preprocessor_ipt(
                    objdb , fw, ipv6_policy);
                prep->setSingleRuleCompileMode(single_rule_id);
                if (inTestMode()) prep->setTestMode();
                if (inEmbeddedMode()) prep->setEmbeddedMode();
                prep->compile();
                delete prep;
            }

            ostringstream automaitc_rules_stream;
            ostringstream automaitc_mangle_stream;
            ostringstream filter_rules_stream;
            ostringstream mangle_rules_stream;
            ostringstream nat_rules_stream;

            bool empty_output = true;

            // First, process branch NAT rulesets, then top NAT ruleset

            NAT *top_nat = NULL;
            for (list<FWObject*>::iterator p=all_nat.begin();
                 p!=all_nat.end(); ++p)
            {
                NAT *nat = NAT::cast(*p);
                if (!nat->matchingAddressFamily(policy_af)) continue;
                if (nat->isTop())
                {
                    top_nat = nat;
                    continue;
                }
                if (! processNatRuleSet(
                        fw,
                        nat,
                        single_rule_id,
                        nat_rules_stream,
                        oscnf.get(),
                        policy_af,
                        minus_n_commands_nat)) empty_output = false;
            }

            if (top_nat &&
                ! processNatRuleSet(
                    fw,
                    top_nat,
                    single_rule_id,
                    nat_rules_stream,
                    oscnf.get(),
                    policy_af,
                    minus_n_commands_nat)) empty_output = false;

            // first process all non-top rule sets, then all top rule sets
            for (int all_top = 0; all_top < 2; ++all_top)
            {
                for (list<FWObject*>::iterator p=all_policies.begin();
                     p!=all_policies.end(); ++p )
                {
                    Policy *policy = Policy::cast(*p);
                    if (!policy->matchingAddressFamily(policy_af)) continue;

                    if (policy->isTop() && all_top == 0) continue;
                    if (!policy->isTop() && all_top == 1) continue;

                    if (! processPolicyRuleSet(
                            fw,
                            policy,
                            single_rule_id,
                            filter_rules_stream,
                            mangle_rules_stream,
                            automaitc_rules_stream,
                            automaitc_mangle_stream,
                            oscnf.get(),
                            policy_af,
                            minus_n_commands_filter,
                            minus_n_commands_mangle)) empty_output = false;
                }
            }

            if (!empty_output && !single_rule_compile_on)
            {
                if (ipv6_policy)
                {
                    have_ipv6 = true;
                    generated_script += "\n\n";
                    generated_script += "# ================ IPv6\n";
                    generated_script += "\n\n";
                } else
                {
                    have_ipv4 = true;
                    generated_script += "\n\n";
                    generated_script += "# ================ IPv4\n";
                    generated_script += "\n\n";
                }
            }

            generated_script += dumpScript(fw,
                                           automaitc_rules_stream.str(),
                                           automaitc_mangle_stream.str(),
                                           nat_rules_stream.str(),
                                           mangle_rules_stream.str(),
                                           filter_rules_stream.str(),
                                           ipv6_policy);
            if (single_rule_compile_on)
                generated_script += "\n\n";
        }

        std::auto_ptr<RoutingCompiler_ipt> routing_compiler(
            new RoutingCompiler_ipt(objdb, fw, false, oscnf.get()));

        RuleSet *routing = RuleSet::cast(fw->getFirstByType(Routing::TYPENAME));
        if (routing)
        {
            routing_compiler->setSourceRuleSet(routing);
            routing_compiler->setRuleSetName(routing->getName());
            routing_compiler->setPersistentObjects(persistent_objects);

            routing_compiler->setSingleRuleCompileMode(single_rule_id);
            routing_compiler->setDebugLevel( dl );
            if (rule_debug_on) routing_compiler->setDebugRule(drr);
            routing_compiler->setVerbose( verbose );
            if (inTestMode()) routing_compiler->setTestMode();
            if (inEmbeddedMode()) routing_compiler->setEmbeddedMode();

            if ( (routing_rules_count=routing_compiler->prolog()) > 0 )
            {
                routing_compiler->compile();
                routing_compiler->epilog();
            }

            if (routing_compiler->haveErrorsAndWarnings())
                all_errors.push_back(routing_compiler->getErrors("").c_str());
        }

        /*
         * compilers detach persistent objects when they finish, this
         * means at this point library persistent_objects is not part
         * of any object tree.
         */
        objdb->reparent(persistent_objects);

        if (haveErrorsAndWarnings())
        {
            all_errors.push_front(getErrors("").c_str());
        }

        if (single_rule_compile_on)
        {
            return formSingleRuleCompileOutput(
                QString::fromUtf8(
                    (getErrors("") + 
                     generated_script +
                     routing_compiler->getCompiledScript()).c_str()));
        }


/*
 * These store generated configuration internally, extract it later using
 * OSConfiguration::getGeneratedFiles();
 */
        oscnf->processFirewallOptions();

/*
 * now write generated scripts to files
 */

        char *timestr = NULL;
        time_t tm;
        struct tm *stm;

        tm = time(NULL);
        stm = localtime(&tm);
        timestr = strdup(ctime(&tm));
        timestr[strlen(timestr)-1] = '\0';

        /*
         * assemble the script and then perhaps post-process it if it
         * should run on Linksys device with sveasoft firmware
         */
        Configlet script_skeleton(fw, "linux24", "script_skeleton");
        script_skeleton.removeComments();

        QString script_buffer;
        QTextStream script(&script_buffer, QIODevice::WriteOnly);

        /*
         * text comes from the compiler in UTF-8 (because all comments
         * and object names are stored in UTF-8 in objects and
         * compilers do not decode). We have a choice: 1) apply
         * QString::fromUtf8() to all strings coming from the compiler
         * to convert to Unicode and rely on QTextStream to convert
         * back to UTF-8 in the generated file, or 2) leavle strings
         * coming from compilers as-is and tell the stream to not
         * covert.
         */

        script_buffer = "";

        script_skeleton.setVariable("shell_debug", shell_dbg);

        script << "PATH=\"/sbin:/usr/sbin:/bin:/usr/bin:${PATH}\"" << "\n";
        script << "export PATH" << "\n";

        script_skeleton.setVariable("path", script_buffer);
        script_buffer = "";

        Configlet script_constants(fw, "linux24", "constants");
        script_skeleton.setVariable("constants", script_constants.expand());

        /*
         * print definitions for variables IPTABLES, IP, LOGGER. Some
         * day we may add a choice of os_variant in the GUI. Right now
         * paths are either default for a given os_variant, or custom
         * strings entered by user in the GUI and stored in firewall
         * options.
         */
        script_skeleton.setVariable("tools",
                                    oscnf->printPathForAllTools(os_variant).c_str());
        script_skeleton.setVariable("shell_functions",
                                    oscnf->printShellFunctions(have_ipv6).c_str());
        script_skeleton.setVariable("run_time_address_tables",
                                    oscnf->printRunTimeAddressTablesCode().c_str());
        script_skeleton.setVariable("using_ipset", oscnf->usingIpSetModule());

        if (supports_prolog_epilog)
        {
            //script_skeleton.setVariable("prolog_epilog",
            //                         oscnf->printPrologEpilogFunctions().c_str());
            script_skeleton.setVariable(
                "prolog_script", 
                fw->getOptionsObject()->getStr("prolog_script").c_str());
            script_skeleton.setVariable(
                "epilog_script", 
                fw->getOptionsObject()->getStr("epilog_script").c_str());
        }

        ostringstream ostr;

        ostr << "# Configure interfaces" << endl;

        if ( options->getBool("configure_bonding_interfaces") ) 
            ostr << oscnf->printBondingInterfaceConfigurationCommands();

        if ( options->getBool("configure_vlan_interfaces")) 
            ostr << oscnf->printVlanInterfaceConfigurationCommands();

        if ( options->getBool("configure_bridge_interfaces") ) 
            ostr << oscnf->printBridgeInterfaceConfigurationCommands();


        if ( options->getBool("configure_interfaces") ||
             options->getBool("manage_virtual_addr"))
        {
            if ( options->getBool("configure_interfaces"))
                ostr << oscnf->printInterfaceConfigurationCommands();
            else
                ostr << oscnf->printVirtualAddressesForNatCommands();
        }

        ostr << oscnf->printCommandsToClearKnownInterfaces();

        ostr << oscnf->printDynamicAddressesConfigurationCommands();

        script_skeleton.setVariable(
            "configure_interfaces", indent(4, QString(ostr.str().c_str())));



        // verify_interfaces checks bridge interfaces so run it
        // after those have been created
        if (options->getBool("verify_interfaces")) 
        {
            list<FWObject*> l2=fw->getByType(Interface::TYPENAME);
            if (l2.empty() )
                script_skeleton.setVariable("verify_interfaces", QString());
            else
                script_skeleton.setVariable("verify_interfaces",
                                            oscnf->printVerifyInterfacesCommands().c_str());
        } else
            script_skeleton.setVariable("verify_interfaces", QString());
    
        string prolog_place = fw->getOptionsObject()->getStr("prolog_place");
        if (prolog_place == "") prolog_place="top";

        /* there is no way to stick prolog commands between iptables
         * reset and iptables rules if we use iptables-restore to
         * activate policy. Therefore, if prolog needs to be ran after
         * iptables flush and we use iptables-restore, we run prolog
         * on top of the script.
         */
        if (!prolog_done &&
            (prolog_place == "top" ||
             (prolog_place == "after_flush" && 
              fw->getOptionsObject()->getBool("use_iptables_restore"))))
        {
            script_skeleton.setVariable("prolog_top", 1);
            script_skeleton.setVariable("prolog_after_interfaces", 0);
            script_skeleton.setVariable("prolog_after_flush", 0);
            prolog_done = true;
        }

        if (!prolog_done && prolog_place == "after_interfaces")
        {
            script_skeleton.setVariable("prolog_top", 0);
            script_skeleton.setVariable("prolog_after_interfaces", 1);
            script_skeleton.setVariable("prolog_after_flush", 0);
            prolog_done = true;
        }

        if (!prolog_done && prolog_place == "after_flush")
        {
            script_skeleton.setVariable("prolog_top", 0);
            script_skeleton.setVariable("prolog_after_interfaces", 0);
            script_skeleton.setVariable("prolog_after_flush", 1);
            prolog_done = true;
        }

        script_skeleton.setVariable("load_modules",
                                    oscnf->generateCodeForProtocolHandlers().c_str());
        script_skeleton.setVariable("load_modules_with_nat", (have_nat)?"nat":"");
        script_skeleton.setVariable("load_modules_with_ipv6", (have_ipv6)?"ipv6":"");

        script_skeleton.setVariable("ip_forward_commands",
                                    oscnf->printIPForwardingCommands().c_str());

        /*
         * script body begins here
         */
        script_buffer = "";

        if (oscnf->haveErrorsAndWarnings())
        {
            all_errors.push_back(oscnf->getErrors("").c_str());
        }

        // convert from UTF8 to make sure localized comments are shown correctly
        // script << oscnf->getCompiledScript().c_str();
        // script << generated_script.c_str();
        // script << routing_compiler->getCompiledScript().c_str();

        script << QString::fromUtf8(oscnf->getCompiledScript().c_str());
        script << QString::fromUtf8(generated_script.c_str());
        script << QString::fromUtf8(routing_compiler->getCompiledScript().c_str());

        script << endl;

        script_skeleton.setVariable("script_body", indent(4, script_buffer));

        script_skeleton.setVariable("timestamp", timestr);
        script_skeleton.setVariable("tz", tzname[stm->tm_isdst]);
        script_skeleton.setVariable("user", user_name);
        script_skeleton.setVariable("database", objdb->getFileName().c_str());

        /*
         * Call reset_all function to flush and reset iptables, but only
         * do this if we do not use iptables_restore. Reset is done as part
         * of iptables-restore script in the latter case and commands are
         * added in PolicyCompiler_ipt::flushAndSetDefaultPolicy()
         */
        script_skeleton.setVariable("not_using_iptables_restore",
                                    ! fw->getOptionsObject()->getBool("use_iptables_restore"));

        script_buffer = "";
        if (have_ipv4) script << "  reset_iptables_v4" << endl;
        if (have_ipv6) script << "  reset_iptables_v6" << endl;
        script_skeleton.setVariable("reset_all", script_buffer);

        script_buffer = "";

        Configlet block_action(fw, "linux24", "block_action");
        if (XMLTools::version_compare(fw_version, "1.4.20") >= 0)
            block_action.setVariable("opt_wait", "-w");
        else
            block_action.setVariable("opt_wait", "");

        block_action.collapseEmptyStrings(true);

        // the name of the option is historical (including the typo)
        if (fw->getOptionsObject()->getBool("add_mgmt_ssh_rule_when_stoped"))
        {
            std::auto_ptr<PolicyCompiler_ipt> policy_compiler =
                createPolicyCompiler(fw, false, NULL,  NULL);
            PolicyCompiler_ipt::PrintRule* print_rule =
                policy_compiler->createPrintRuleProcessor();
            print_rule->setContext(policy_compiler.get());
            print_rule->_printBackupSSHAccessRules(&block_action);
        } else
        {
            block_action.setVariable("mgmt_access", 0);
        }

        script_skeleton.setVariable("block_action", block_action.expand());


        Configlet stop_action(fw, "linux24", "stop_action");
        stop_action.collapseEmptyStrings(true);
        stop_action.setVariable("have_ipv4", have_ipv4);
        stop_action.setVariable("have_ipv6", have_ipv6);

        if (XMLTools::version_compare(fw_version, "1.4.20") >= 0)
            stop_action.setVariable("opt_wait", "-w");
        else
            stop_action.setVariable("opt_wait", "");

        script_skeleton.setVariable("stop_action", stop_action.expand());



        Configlet status_action(fw, "linux24", "status_action");
        status_action.collapseEmptyStrings(true);
        script_skeleton.setVariable("status_action", status_action.expand());

        Configlet top_comment(fw, "linux24", "top_comment");

        top_comment.setVariable("version", VERSION);
        top_comment.setVariable("timestamp", timestr);
        top_comment.setVariable("tz", tzname[stm->tm_isdst]);
        top_comment.setVariable("user", user_name);
        top_comment.setVariable("database", objdb->getFileName().c_str());

        determineOutputFileNames(cluster, fw, !cluster_id.empty(),
                                 QStringList(""), QStringList("fw"),
                                 QStringList("script_name_on_firewall"));

        script_buffer = "";
        script << MANIFEST_MARKER
               << "* "
               << this->escapeFileName(file_names[FW_FILE]);

        if (!remote_file_names[FW_FILE].isEmpty())
            script << " " << this->escapeFileName(remote_file_names[FW_FILE]);
        script << "\n";

        /* Add additional files to manifest if specified.  Currently there
         * are no GUI controls to let user provide alternative names for
         * these on the firewall. See description of manifest format in
         * comments in src/gui/FirewallInstaller.cpp
         */
        map<string, string> file_list = oscnf->getGeneratedFiles();
        if (!file_list.empty())
        {
            info(" Adding additional files to manifest");
            map<string, string>::const_iterator c_iter = file_list.begin();
            for (; c_iter != file_list.end(); ++c_iter)
            {
                string name = c_iter->first;
                string dest = c_iter->second;
                script << MANIFEST_MARKER << this->escapeFileName(name.c_str());
                if (!dest.empty()) script << " " << dest;
                script << "\n";
            }
        }

        top_comment.setVariable("manifest", script_buffer);
        top_comment.setVariable("platform", platform.c_str());
        top_comment.setVariable("fw_version", fw_version.c_str());
        top_comment.setVariable("comment", prepend("# ", fw->getComment().c_str()));

        script_skeleton.setVariable("top_comment", top_comment.expand());
        script_skeleton.setVariable("errors_and_warnings",
                                    prepend("# ", all_errors.join("\n")));

        info("Output file name: " + file_names[FW_FILE].toStdString());

        QFile fw_file(file_names[FW_FILE]);
        if (fw_file.open(QIODevice::WriteOnly))
        {
            QTextStream fw_str(&fw_file);
            fw_str << script_skeleton.expand();
            fw_file.close();
            fw_file.setPermissions(QFile::ReadOwner | QFile::WriteOwner |
                                   QFile::ReadGroup | QFile::ReadOther |
                                   QFile::ExeOwner | 
                                   QFile::ExeGroup |
                                   QFile::ExeOther );

            info(" Compiled successfully");

        } else
        {
            QString err(" Failed to open file %1 for writing: %2; Current dir: %3");
            abort(err.arg(fw_file.fileName())
                  .arg(fw_file.error()).arg(QDir::current().path()).toStdString());
        }

        free(timestr);

        if (!all_errors.isEmpty())
            status = BaseCompiler::FWCOMPILER_WARNING;

    }
    catch (FWException &ex)
    {
        status = BaseCompiler::FWCOMPILER_ERROR;
        return QString::fromUtf8(ex.toString().c_str());
    }
    
    return "";
}
예제 #15
0
/**
 * Print shell functions used by the script. If argument (boolean) is true,
 * do not add comments.
 */
string OSConfigurator_linux24::printShellFunctions(bool have_ipv6)
{
    QStringList output;
    FWOptions* options = fw->getOptionsObject();

    string version = fw->getStr("version");
    // string host_os = fw->getStr("host_OS");
    // string os_family = Resources::os_res[host_os]->
    //     getResourceStr("/FWBuilderResources/Target/family");

    Configlet shell_functions(fw, "linux24", "shell_functions");
    output.push_back(shell_functions.expand());

/* check if package iproute2 is installed, but do this only if
 * we really need /usr/sbin/ip 
 */
    Configlet configlet(fw, "linux24", "check_utilities");
    configlet.removeComments();
    configlet.collapseEmptyStrings(true);

    configlet.setVariable("load_modules", options->getBool("load_modules"));

    if (options->getBool("load_modules") ||
        options->getBool("configure_vlan_interfaces") ||
        options->getBool("configure_bonding_interfaces"))
    {
        configlet.setVariable("need_modprobe", true);
    }

    if (options->getBool("verify_interfaces") || 
        options->getBool("manage_virtual_addr") ||
        options->getBool("configure_interfaces") )
    {
        configlet.setVariable("need_vconfig", 
                              options->getBool("configure_vlan_interfaces"));
        configlet.setVariable("need_brctl", 
                              options->getBool("configure_bridge_interfaces"));
        configlet.setVariable("need_ifenslave", 
                              options->getBool("configure_bonding_interfaces"));
    }

    configlet.setVariable("need_ipset", using_ipset);

    configlet.setVariable("need_iptables_restore",
                          options->getBool("use_iptables_restore"));

    configlet.setVariable("need_ip6tables_restore",
                          have_ipv6 && options->getBool("use_iptables_restore"));

    output.push_back(configlet.expand());

    /*
     * Generate commands to reset all tables and chains and set
     * default policy
     */
    Configlet reset_iptables(fw, "linux24", "reset_iptables");
    if (XMLTools::version_compare(version, "1.4.20") >= 0)
        reset_iptables.setVariable("opt_wait", "-w");
    else
        reset_iptables.setVariable("opt_wait", "");

    output.push_back(reset_iptables.expand());

    Configlet addr_conf(fw, "linux24", "update_addresses");
    output.push_back(addr_conf.expand());

    if (options->getBool("configure_vlan_interfaces"))
    {
        Configlet conf(fw, "linux24", "update_vlans");
        output.push_back(conf.expand());
    }

    if (options->getBool("configure_bridge_interfaces"))
    {
        Configlet conf(fw, "linux24", "update_bridge");
        output.push_back(conf.expand());
    }

    if (options->getBool("configure_bonding_interfaces"))
    {
        Configlet conf(fw, "linux24", "update_bonding");
        output.push_back(conf.expand());
    }

    return output.join("\n").toStdString();
}