From f3248ac627f55033408696d3485035f89cbb169b Mon Sep 17 00:00:00 2001 From: Nodir Temirkhodjaev Date: Sun, 14 Apr 2024 10:34:02 +0300 Subject: [PATCH] UI: ConfUtil: Prepare writeRules() --- src/driver/common/fortconf.h | 3 +- src/ui/FortFirewallUI.pro | 1 + src/ui/conf/confappmanager.cpp | 5 +- src/ui/conf/confappmanager.h | 2 +- src/ui/conf/confrulemanager.cpp | 122 ++++++++++++++++++++++++++--- src/ui/conf/confrulemanager.h | 14 +++- src/ui/util/conf/confappswalker.h | 2 +- src/ui/util/conf/confruleswalker.h | 30 +++++++ src/ui/util/conf/confutil.cpp | 21 ++++- src/ui/util/conf/confutil.h | 9 ++- 10 files changed, 187 insertions(+), 22 deletions(-) create mode 100644 src/ui/util/conf/confruleswalker.h diff --git a/src/driver/common/fortconf.h b/src/driver/common/fortconf.h index 5df93294..1eacb946 100644 --- a/src/driver/common/fortconf.h +++ b/src/driver/common/fortconf.h @@ -148,7 +148,7 @@ typedef struct fort_conf_rule typedef struct fort_conf_rules { - UINT32 rule_off[FORT_CONF_RULE_MAX]; + UINT16 max_rule_id; char data[4]; } FORT_CONF_RULES, *PFORT_CONF_RULES; @@ -159,6 +159,7 @@ typedef struct fort_conf_rule_flag UCHAR enabled; } FORT_CONF_RULE_FLAG, *PFORT_CONF_RULE_FLAG; +#define FORT_CONF_RULES_DATA_OFF offsetof(FORT_CONF_RULES, data) #define FORT_CONF_RULE_SIZE(rule) \ (sizeof(FORT_CONF_RULE) + ((rule)->has_zones ? sizeof(FORT_CONF_RULE_ZONES) : 0) \ + (rule)->set_count * sizeof(UINT16)) diff --git a/src/ui/FortFirewallUI.pro b/src/ui/FortFirewallUI.pro index 71ba292f..63d2fd90 100644 --- a/src/ui/FortFirewallUI.pro +++ b/src/ui/FortFirewallUI.pro @@ -397,6 +397,7 @@ HEADERS += \ util/conf/addressrange.h \ util/conf/appparseoptions.h \ util/conf/confappswalker.h \ + util/conf/confruleswalker.h \ util/conf/confutil.h \ util/dateutil.h \ util/device.h \ diff --git a/src/ui/conf/confappmanager.cpp b/src/ui/conf/confappmanager.cpp index 885467b7..fadc6cd4 100644 --- a/src/ui/conf/confappmanager.cpp +++ b/src/ui/conf/confappmanager.cpp @@ -62,7 +62,8 @@ const char *const sqlSelectAppById = "SELECT" SELECT_APP_FIELDS " FROM app t" const char *const sqlSelectApps = "SELECT" SELECT_APP_FIELDS " FROM app t" " JOIN app_group g ON g.app_group_id = t.app_group_id" - " LEFT JOIN app_alert alert ON alert.app_id = t.app_id;"; + " LEFT JOIN app_alert alert ON alert.app_id = t.app_id" + " ORDER BY t.path;"; const char *const sqlSelectAppsToPurge = "SELECT app_id, path FROM app" " WHERE is_wildcard = 0 AND parked = 0;"; @@ -491,7 +492,7 @@ QVector ConfAppManager::collectObsoleteApps(quint32 driveMask) return appIdList; } -bool ConfAppManager::walkApps(const std::function &func) +bool ConfAppManager::walkApps(const std::function &func) const { SqliteStmt stmt; if (!DbQuery(sqliteDb()).sql(sqlSelectApps).prepare(stmt)) diff --git a/src/ui/conf/confappmanager.h b/src/ui/conf/confappmanager.h index 3326aac2..fc4889be 100644 --- a/src/ui/conf/confappmanager.h +++ b/src/ui/conf/confappmanager.h @@ -43,7 +43,7 @@ public: virtual bool updateAppsBlocked( const QVector &appIdList, bool blocked, bool killProcess); - bool walkApps(const std::function &func) override; + bool walkApps(const std::function &func) const override; bool saveAppBlocked(const App &app); void updateAppEndTimes(); diff --git a/src/ui/conf/confrulemanager.cpp b/src/ui/conf/confrulemanager.cpp index 8917522c..bdcd3ac3 100644 --- a/src/ui/conf/confrulemanager.cpp +++ b/src/ui/conf/confrulemanager.cpp @@ -18,6 +18,25 @@ namespace { const QLoggingCategory LC("confRule"); +#define SELECT_RULE_FIELDS \ + " t.rule_id," \ + " t.enabled," \ + " t.blocked," \ + " t.exclusive," \ + " t.rule_text," \ + " t.rule_type," \ + " t.accept_zones," \ + " t.reject_zones" + +const char *const sqlSelectRules = "SELECT" SELECT_RULE_FIELDS " FROM rule t" + " ORDER BY t.rule_id;"; + +const char *const sqlSelectRuleSets = "SELECT t.rule_id, t.sub_rule_id" + " FROM rule_set t" + " ORDER BY t.rule_id, t.order_index;"; + +const char *const sqlSelectMaxRuleId = "SELECT MAX(rule_id) FROM rule;"; + const char *const sqlInsertRule = "INSERT INTO rule(rule_id, enabled, blocked, exclusive," " name, notes, rule_text, rule_type," " accept_zones, reject_zones, mod_time)" @@ -191,8 +210,6 @@ bool ConfRuleManager::addOrUpdateRule(Rule &rule) .sql(sqlSelectRuleIds) .vars({ ConfUtil::ruleMaxCount() }) .getFreeId(/*maxId=*/ConfUtil::ruleMaxCount() - 1); - } else { - updateDriverRuleFlag(rule.ruleId, rule.enabled); } const QVariantList vars = { @@ -220,6 +237,8 @@ bool ConfRuleManager::addOrUpdateRule(Rule &rule) if (!ok) return false; + updateDriverRules(); + if (isNew) { emit ruleAdded(); } else { @@ -251,6 +270,8 @@ bool ConfRuleManager::deleteRule(int ruleId) if (ok) { emit ruleRemoved(ruleId); + + updateDriverRules(); } return ok; @@ -296,16 +317,97 @@ bool ConfRuleManager::updateRuleEnabled(int ruleId, bool enabled) return ok; } -void ConfRuleManager::updateDriverRules(quint32 rulesMask, quint32 enabledMask, quint32 dataSize, - const QList &rulesData) +bool ConfRuleManager::walkRules(ruleset_map_t &ruleSetMap, ruleid_arr_t &ruleIds, int &maxRuleId, + const std::function &func) const +{ + bool ok = false; + + sqliteDb()->beginTransaction(); + + maxRuleId = DbQuery(sqliteDb()).sql(sqlSelectMaxRuleId).execute().toInt(); + + walkRulesMap(ruleSetMap, ruleIds); + + ok = walkRulesLoop(func); + + sqliteDb()->commitTransaction(); + + return ok; +} + +void ConfRuleManager::walkRulesMap(ruleset_map_t &ruleSetMap, ruleid_arr_t &ruleIds) const +{ + SqliteStmt stmt; + if (!DbQuery(sqliteDb()).sql(sqlSelectRuleSets).prepare(stmt)) + return; + + int prevRuleId = 0; + int prevIndex = 0; + + int index = 0; + for (;;) { + const bool isStepRow = (stmt.step() == SqliteStmt::StepRow); + + const int ruleId = stmt.columnInt(0); + const int subRuleId = stmt.columnInt(1); + + if (prevRuleId != ruleId) { + const RuleSetIndex ruleSetIndex = { + .index = quint32(prevIndex), + .count = quint8(index - prevIndex), + }; + + ruleSetMap.insert(prevRuleId, ruleSetIndex); + + prevRuleId = ruleId; + prevIndex = index; + } + + ruleIds.append(subRuleId); + + ++index; + + if (!isStepRow) + break; + } +} + +bool ConfRuleManager::walkRulesLoop(const std::function &func) const +{ + SqliteStmt stmt; + if (!DbQuery(sqliteDb()).sql(sqlSelectRules).prepare(stmt)) + return false; + + while (stmt.step() == SqliteStmt::StepRow) { + Rule rule; + fillRule(rule, stmt); + + if (!func(rule)) + return false; + } + + return true; +} + +void ConfRuleManager::fillRule(Rule &rule, const SqliteStmt &stmt) +{ + rule.ruleId = stmt.columnInt(0); + rule.enabled = stmt.columnBool(1); + rule.blocked = stmt.columnBool(2); + rule.exclusive = stmt.columnBool(3); + rule.ruleText = stmt.columnText(4); + rule.ruleType = Rule::RuleType(stmt.columnInt(5)); + rule.acceptZones = stmt.columnUInt64(6); + rule.rejectZones = stmt.columnUInt64(7); +} + +void ConfRuleManager::updateDriverRules() { ConfUtil confUtil; -#if 0 - const int entrySize = confUtil.writeRules(rulesMask, enabledMask, dataSize, rulesData); + confUtil.writeRules(*this); - driverWriteRules(confUtil, confUtil.buffer(), entrySize); -#endif + // driverWriteRules(confUtil, confUtil.buffer(), entrySize); } bool ConfRuleManager::updateDriverRuleFlag(int ruleId, bool enabled) @@ -313,9 +415,9 @@ bool ConfRuleManager::updateDriverRuleFlag(int ruleId, bool enabled) ConfUtil confUtil; #if 0 - const int entrySize = confUtil.writeRuleFlag(ruleId, enabled); + confUtil.writeRuleFlag(ruleId, enabled); - return driverWriteRules(confUtil, confUtil.buffer(), entrySize, /*onlyFlags=*/true); + return driverWriteRules(confUtil, confUtil.buffer(), /*onlyFlags=*/true); #endif return true; } diff --git a/src/ui/conf/confrulemanager.h b/src/ui/conf/confrulemanager.h index 9c6d6f3e..42dc863c 100644 --- a/src/ui/conf/confrulemanager.h +++ b/src/ui/conf/confrulemanager.h @@ -7,11 +7,12 @@ #include #include +#include #include class ConfManager; -class ConfRuleManager : public QObject, public IocService +class ConfRuleManager : public QObject, public ConfRulesWalker, public IocService { Q_OBJECT @@ -35,8 +36,10 @@ public: virtual bool updateRuleName(int ruleId, const QString &ruleName); virtual bool updateRuleEnabled(int ruleId, bool enabled); - void updateDriverRules(quint32 rulesMask, quint32 enabledMask, quint32 dataSize, - const QList &rulesData); + bool walkRules(ruleset_map_t &ruleSetMap, ruleid_arr_t &ruleIds, int &maxRuleId, + const std::function &func) const override; + + void updateDriverRules(); signals: void ruleAdded(); @@ -44,6 +47,11 @@ signals: void ruleUpdated(); private: + void walkRulesMap(ruleset_map_t &ruleSetMap, ruleid_arr_t &ruleIds) const; + bool walkRulesLoop(const std::function &func) const; + + static void fillRule(Rule &rule, const SqliteStmt &stmt); + bool updateDriverRuleFlag(int ruleId, bool enabled); bool beginTransaction(); diff --git a/src/ui/util/conf/confappswalker.h b/src/ui/util/conf/confappswalker.h index 72e4c5cc..9c2f6380 100644 --- a/src/ui/util/conf/confappswalker.h +++ b/src/ui/util/conf/confappswalker.h @@ -12,7 +12,7 @@ using walkAppsCallback = bool(App &app); class ConfAppsWalker { public: - virtual bool walkApps(const std::function &func) = 0; + virtual bool walkApps(const std::function &func) const = 0; }; #endif // CONFAPPSWALKER_H diff --git a/src/ui/util/conf/confruleswalker.h b/src/ui/util/conf/confruleswalker.h new file mode 100644 index 00000000..eceee498 --- /dev/null +++ b/src/ui/util/conf/confruleswalker.h @@ -0,0 +1,30 @@ +#ifndef CONFRULESWALKER_H +#define CONFRULESWALKER_H + +#include +#include +#include + +#include + +#include + +struct RuleSetIndex +{ + quint32 index : 24; + quint32 count : 8; +}; + +using ruleset_map_t = QHash; +using ruleid_arr_t = QVector; + +using walkRulesCallback = bool(Rule &rule); + +class ConfRulesWalker +{ +public: + virtual bool walkRules(ruleset_map_t &ruleSetMap, ruleid_arr_t &ruleIds, int &maxRuleId, + const std::function &func) const = 0; +}; + +#endif // CONFRULESWALKER_H diff --git a/src/ui/util/conf/confutil.cpp b/src/ui/util/conf/confutil.cpp index 4f9ac429..4ef5f79d 100644 --- a/src/ui/util/conf/confutil.cpp +++ b/src/ui/util/conf/confutil.cpp @@ -15,6 +15,7 @@ #include #include "confappswalker.h" +#include "confruleswalker.h" #define APP_GROUP_MAX FORT_CONF_GROUP_MAX #define APP_GROUP_NAME_MAX 128 @@ -218,7 +219,7 @@ void ConfUtil::writeServices(const QVector &services, int runningSe } bool ConfUtil::write( - const FirewallConf &conf, ConfAppsWalker *confAppsWalker, EnvManager &envManager) + const FirewallConf &conf, const ConfAppsWalker *confAppsWalker, EnvManager &envManager) { WriteConfArgs wca = { .conf = conf, .ad = { .addressRanges = addrranges_arr_t(conf.addressGroups().size()) } }; @@ -287,6 +288,22 @@ bool ConfUtil::writeAppEntry(const App &app, bool isNew) return true; } +bool ConfUtil::writeRules(const ConfRulesWalker &confRulesWalker) +{ + ruleset_map_t ruleSetMap; + ruleid_arr_t ruleIds; + int maxRuleId; + + return confRulesWalker.walkRules(ruleSetMap, ruleIds, maxRuleId, [&](Rule &rule) -> bool { + if (buffer().isEmpty()) { + } + + const auto ruleSetIndex = ruleSetMap[rule.ruleId]; + + return true; + }); +} + void ConfUtil::writeZone(const IpRange &ipRange) { const int addrSize = FORT_CONF_ADDR_LIST_SIZE( @@ -467,7 +484,7 @@ bool ConfUtil::parseAppGroups(EnvManager &envManager, const QList &a } bool ConfUtil::parseExeApps( - EnvManager &envManager, ConfAppsWalker *confAppsWalker, AppParseOptions &opt) + EnvManager &envManager, const ConfAppsWalker *confAppsWalker, AppParseOptions &opt) { if (Q_UNLIKELY(!confAppsWalker)) return true; diff --git a/src/ui/util/conf/confutil.h b/src/ui/util/conf/confutil.h index 51a79a25..0203f5a4 100644 --- a/src/ui/util/conf/confutil.h +++ b/src/ui/util/conf/confutil.h @@ -14,6 +14,7 @@ class AddressGroup; class App; class AppGroup; class ConfAppsWalker; +class ConfRulesWalker; class EnvManager; class FirewallConf; @@ -51,10 +52,13 @@ public slots: void writeVersion(); void writeServices(const QVector &services, int runningServicesCount); - bool write(const FirewallConf &conf, ConfAppsWalker *confAppsWalker, EnvManager &envManager); + bool write( + const FirewallConf &conf, const ConfAppsWalker *confAppsWalker, EnvManager &envManager); void writeFlags(const FirewallConf &conf); bool writeAppEntry(const App &app, bool isNew = false); + bool writeRules(const ConfRulesWalker &confRulesWalker); + void writeZone(const IpRange &ipRange); void writeZones(quint32 zonesMask, quint32 enabledMask, quint32 dataSize, const QList &zonesData); @@ -92,7 +96,8 @@ private: bool parseAppGroups(EnvManager &envManager, const QList &appGroups, ParseAppGroupsArgs &gr, AppParseOptions &opt); - bool parseExeApps(EnvManager &envManager, ConfAppsWalker *confAppsWalker, AppParseOptions &opt); + bool parseExeApps( + EnvManager &envManager, const ConfAppsWalker *confAppsWalker, AppParseOptions &opt); bool parseAppsText(EnvManager &envManager, App &app, AppParseOptions &opt);