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;
}
예제 #2
0
void Importer::pushRule()
{
    assert(current_ruleset!=NULL);
    assert(current_rule!=NULL);
    // populate all elements of the rule

    PolicyRule *rule = PolicyRule::cast(current_rule);

    FWOptions  *ropt = current_rule->getOptionsObject();
    assert(ropt!=NULL);

    if (action=="permit")
    {
        rule->setAction(PolicyRule::Accept);
        ropt->setBool("stateless", false);
    }

    if (action=="deny")
    {
        rule->setAction(PolicyRule::Deny);
        ropt->setBool("stateless", true);
    }

    rule->setDirection(PolicyRule::Both);

    addSrc();
    addDst();
    addSrv();

    addLogging();

    // then add it to the current ruleset
    current_ruleset->ruleset->add(current_rule);

    if (error_tracker->hasWarnings())
    {
        QStringList warn = error_tracker->getWarnings();
        // parser errors and warnings are added to the log by
        // PFCfgParser::reportError() and PFCfgParser::reportWarning()
        // so we dont need to add them again here
        foreach(QString w, warn)
        {
            if (!w.startsWith("Parser warning:")) addMessageToLog("Warning: " + w);
        }
        markCurrentRuleBad();
    }
예제 #3
0
void Importer::newPolicyRule()
{
    if (fwbdebug) qDebug() << "Importer::newPolicyRule()";

    FWObjectDatabase *dbroot = getFirewallObject()->getRoot();
    FWObject *nobj = dbroot->create(PolicyRule::TYPENAME);
    current_rule = Rule::cast(nobj);

    // check if all child objects were populated properly
    FWOptions  *ropt = current_rule->getOptionsObject();
    assert(ropt!=NULL);
    ropt->setBool("stateless", true);
}
bool PolicyCompiler_ipf::checkForKeepState::processNext()
{
    PolicyRule *rule=getNext(); if (rule==NULL) return false;
    tmp_queue.push_back(rule);

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

    if (! ICMPService::isA(srv) && 
        ! UDPService::isA(srv)  &&
        ! TCPService::isA(srv) )    ruleopt->setBool("stateless",true);

    return true;
}
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;
}
bool PolicyCompiler_ipf::doDstNegation::processNext()
{
    PolicyRule *rule=getNext(); if (rule==NULL) return false;

    RuleElementDst *dst=rule->getDst();

    if (dst->getNeg()) {
        RuleElementDst *ndst;
	PolicyRule     *r;
        FWOptions *ruleopt;

	r= compiler->dbcopy->createPolicyRule();
	compiler->temp_ruleset->add(r);
	r->duplicate(rule);
	r->setAction(PolicyRule::Continue);
	r->setLogging(false);
        ndst=r->getDst();
        ndst->setNeg(false);
	r->setBool("quick",false);
        r->setBool("skip_check_for_duplicates",true);
        ruleopt = r->getOptionsObject();
        ruleopt->setBool("stateless", true);
	tmp_queue.push_back(r);

	r= compiler->dbcopy->createPolicyRule();
	compiler->temp_ruleset->add(r);
	r->duplicate(rule);
        ndst=r->getDst();
        ndst->setNeg(false);
	ndst->clearChildren();
	ndst->setAnyElement();
	r->setBool("quick",true);
        r->setBool("skip_check_for_duplicates",true);
	tmp_queue.push_back(r);

	return true;
    }
    tmp_queue.push_back(rule);
    return true;
}
예제 #7
0
void PFImporter::addLogging()
{
    PolicyRule *rule = PolicyRule::cast(current_rule);
    FWOptions *ropt = rule->getOptionsObject();

    /*
      alerts         Immediate action needed           (severity=1)
      critical       Critical conditions               (severity=2)
      debugging      Debugging messages                (severity=7)
      disable        Disable log option on this ACL element, (no log at all)
      emergencies    System is unusable                (severity=0)
      errors         Error conditions                  (severity=3)
      inactive       Keyword for disabling an ACL element
      informational  Informational messages            (severity=6)
      interval       Configure log interval, default value is 300 sec
      notifications  Normal but significant conditions (severity=5)
      warnings       Warning conditions                (severity=4)
    */
    QMap<QString, QString> logging_levels;

    logging_levels["alerts"] = "alert";
    logging_levels["critical"] = "crit";
    logging_levels["debugging"] = "debug";
    logging_levels["emergencies"] = "";
    logging_levels["errors"] = "error";
    logging_levels["informational"] = "info";
    logging_levels["notifications"] = "notice";
    logging_levels["warnings"] = "warning";
    logging_levels["0"] = "";
    logging_levels["1"] = "alert";
    logging_levels["2"] = "crit";
    logging_levels["3"] = "error";
    logging_levels["4"] = "warning";
    logging_levels["5"] = "notice";
    logging_levels["6"] = "info";
    logging_levels["7"] = "debug";

    // QStringList log_levels = getLogLevels("pix");

    rule->setLogging(logging);

    QString log_level_qs = log_level.c_str();
    if ( ! log_level_qs.isEmpty())
    {
        if (logging_levels.count(log_level_qs) != 0)
            ropt->setStr("log_level", logging_levels[log_level_qs].toStdString());
        else
            ropt->setStr("log_level", log_level);

        if (log_level_qs == "disable" || log_level_qs == "inactive")
            ropt->setBool("disable_logging_for_this_rule", true);
    }

    if ( ! log_interval.empty())
    {
        bool ok = false;
        int log_interval_int = QString(log_interval.c_str()).toInt(&ok);
        if (ok)
            ropt->setInt("log_interval", log_interval_int);
    }
}
예제 #8
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 "";
}