bool ProcFilter::ParseConfig()

in ProcFilter.cpp [54:277]


bool ProcFilter::ParseConfig(const Config& config) {
    if (config.HasKey(CONFIG_PARAM_NAME)) {
        auto doc = config.GetJSON(CONFIG_PARAM_NAME);
        if (!doc.IsArray()) {
            return false;
        }
        int idx = 0;
        for (auto it = doc.Begin(); it != doc.End(); ++it, idx++) {
            if (it->IsObject()) {
                uint32_t match_mask = 0;
                int depth = 0;
                uint32_t uid = INVALID_ID;
                uint32_t gid = INVALID_ID;
                std::string user;
                std::string group;
                std::vector<std::string> syscalls;
                std::string exeMatchValue;
                std::vector<cmdlineFilter> cmdlineFilters;

                rapidjson::Value::ConstMemberIterator mi;

                mi = it->FindMember("depth");
                if (mi != it->MemberEnd()) {
                    if (mi->value.IsInt()) {
                        int i = mi->value.GetInt();
                        if (i < -1) {
                            Logger::Error("Invalid entry (%s) at (%d) in config for '%s'", mi->name.GetString(), idx, CONFIG_PARAM_NAME.c_str());
                            _filters.clear();
                            return false;
                        }
                        depth = i;
                    } else {
                        Logger::Error("Invalid entry (%s) at (%d) in config for '%s'", mi->name.GetString(), idx, CONFIG_PARAM_NAME.c_str());
                        _filters.clear();
                        return false;
                    }
                }

                mi = it->FindMember("user");
                if (mi != it->MemberEnd()) {
                    if (mi->value.IsString()) {
                        user = std::string(mi->value.GetString(), mi->value.GetStringLength());
                        if (is_number(user)) {
                            uid = (uint32_t)std::stol(user);
                        } else {
                            uid = (uint32_t)_user_db->UserNameToUid(user);
                        }
                        if (uid == INVALID_ID) {
                            Logger::Error("Invalid entry (%s) at (%d) in config for '%s'", mi->name.GetString(), idx, CONFIG_PARAM_NAME.c_str());
                            _filters.clear();
                            return false;
                        }
                        match_mask |= PFS_MATCH_UID;
                    } else {
                        Logger::Error("Invalid entry (%s) at (%d) in config for '%s'", mi->name.GetString(), idx, CONFIG_PARAM_NAME.c_str());
                        _filters.clear();
                        return false;
                    }
                }

                mi = it->FindMember("group");
                if (mi != it->MemberEnd()) {
                    if (mi->value.IsString()) {
                        group = std::string(mi->value.GetString(), mi->value.GetStringLength());
                        if (is_number(group)) {
                            gid = (uint32_t)std::stol(group);
                        } else {
                            gid = (uint32_t)_user_db->GroupNameToGid(group);
                        }
                        if (gid == INVALID_ID) {
                            Logger::Error("Invalid entry (%s) at (%d) in config for '%s'", mi->name.GetString(), idx, CONFIG_PARAM_NAME.c_str());
                            _filters.clear();
                            return false;
                        }
                        match_mask |= PFS_MATCH_GID;
                    } else {
                        Logger::Error("Invalid entry (%s) at (%d) in config for '%s'", mi->name.GetString(), idx, CONFIG_PARAM_NAME.c_str());
                        _filters.clear();
                        return false;
                    }
                }

                mi = it->FindMember("syscalls");
                if (mi != it->MemberEnd()) {
                    if (mi->value.IsArray()) {
                        if (!syscalls.empty()) {
                            syscalls.clear();
                        }
                        bool includesExclude = false;
                        bool includesInclude = false;
                        for (auto it2 = mi->value.Begin(); it2 != mi->value.End(); ++it2) {
                            syscalls.emplace_back(std::string(it2->GetString(), it2->GetStringLength()));
                            if (it2->GetString()[0] == '!') {
                                includesExclude = true;
                            } else {
                                includesInclude = true;
                            }
                        }
                        // If all the syscalls are excludes (!syscall) then there is an implicit inclusion
                        // of all other syscalls.
                        // If there is a mixture of includes and excludes then includes are the default.
                        if (includesExclude && !includesInclude) {
                            syscalls.emplace_back(std::string("*"));
                        }
                    } else {
                        Logger::Error("Invalid entry (%s) at (%d) in config for '%s'", mi->name.GetString(), idx, CONFIG_PARAM_NAME.c_str());
                        _filters.clear();
                        return false;
                    }
                }

                mi = it->FindMember("exeMatchType");
                if (mi != it->MemberEnd()) {
                    if (mi->value.IsString()) {
                        if (!strcmp(mi->value.GetString(), "MatchEquals")) {
                            match_mask |= PFS_MATCH_EXE_EQUALS;
                        } else if (!strcmp(mi->value.GetString(), "MatchStartsWith")) {
                            match_mask |= PFS_MATCH_EXE_STARTSWITH;
                        } else if (!strcmp(mi->value.GetString(), "MatchContains")) {
                            match_mask |= PFS_MATCH_EXE_CONTAINS;
                        } else if (!strcmp(mi->value.GetString(), "MatchRegex")) {
                            match_mask |= PFS_MATCH_EXE_REGEX;
                        } else {
                            Logger::Error("Invalid entry (%s) at (%d) in config for '%s'", mi->name.GetString(), idx, CONFIG_PARAM_NAME.c_str());
                            _filters.clear();
                            return false;
                        }
                    } else {
                        Logger::Error("Invalid entry (%s) at (%d) in config for '%s'", mi->name.GetString(), idx, CONFIG_PARAM_NAME.c_str());
                        _filters.clear();
                        return false;
                    }
                }

                mi = it->FindMember("exeMatchValue");
                if (mi != it->MemberEnd()) {
                    if (mi->value.IsString()) {
                        exeMatchValue = std::string(mi->value.GetString(), mi->value.GetStringLength());
                    } else {
                        Logger::Error("Invalid entry (%s) at (%d) in config for '%s'", mi->name.GetString(), idx, CONFIG_PARAM_NAME.c_str());
                        _filters.clear();
                        return false;
                    }
                }

                mi = it->FindMember("cmdlineFilters");
                if (mi != it->MemberEnd()) {
                    if (mi->value.IsArray()) {
                        if (!cmdlineFilters.empty()) {
                            cmdlineFilters.clear();
                        }
                        for (auto it2 = mi->value.Begin(); it2 != mi->value.End(); ++it2) {
                            if (it2->IsObject()) {
                                cmdlineFilter cf;
                                rapidjson::Value::ConstMemberIterator mi2;
                                mi2 = it2->FindMember("matchType");
                                if (mi2 != it2->MemberEnd()) {
                                    if (mi2->value.IsString()) {
                                        if (!strcmp(mi2->value.GetString(), "MatchEquals")) {
                                            cf._matchType = MatchEquals;
                                        } else if (!strcmp(mi2->value.GetString(), "MatchStartsWith")) {
                                            cf._matchType = MatchStartsWith;
                                        } else if (!strcmp(mi2->value.GetString(), "MatchContains")) {
                                            cf._matchType = MatchContains;
                                        } else if (!strcmp(mi2->value.GetString(), "MatchRegex")) {
                                            cf._matchType = MatchRegex;
                                        } else {
                                            Logger::Error("Invalid entry (%s) at (%d) in config for '%s'", mi->name.GetString(), idx, CONFIG_PARAM_NAME.c_str());
                                            _filters.clear();
                                            return false;
                                        }
                                    } else {
                                        Logger::Error("Invalid entry (%s) at (%d) in config for '%s'", mi->name.GetString(), idx, CONFIG_PARAM_NAME.c_str());
                                        _filters.clear();
                                        return false;
                                    }
                                } else {
                                    Logger::Error("Invalid entry (%s) at (%d) in config for '%s' is missing", mi->name.GetString(), idx, CONFIG_PARAM_NAME.c_str());
                                    _filters.clear();
                                    return false;
                                }

                                mi2 = it2->FindMember("matchValue");
                                if (mi2 != it2->MemberEnd()) {
                                    if (mi2->value.IsString()) {
                                        cf._matchValue = std::string(mi2->value.GetString(), mi2->value.GetStringLength());
                                    } else {
                                        Logger::Error("Invalid entry (%s) at (%d) in config for '%s'", mi->name.GetString(), idx, CONFIG_PARAM_NAME.c_str());
                                        _filters.clear();
                                        return false;
                                    }
                                } else {
                                    Logger::Error("Invalid entry (%s) at (%d) in config for '%s' is missing", mi->name.GetString(), idx, CONFIG_PARAM_NAME.c_str());
                                    _filters.clear();
                                    return false;
                                }

                                cmdlineFilters.emplace_back(cf);
                            } else {
                                Logger::Error("Invalid entry (%s) at (%d) in config for '%s'", mi->name.GetString(), idx, CONFIG_PARAM_NAME.c_str());
                                _filters.clear();
                                return false;
                            }
                        }
                    } else {
                        Logger::Error("Invalid entry (%s) at (%d) in config for '%s'", mi->name.GetString(), idx, CONFIG_PARAM_NAME.c_str());
                        _filters.clear();
                        return false;
                    }
                }

                if (syscalls.empty()) {
                    syscalls.emplace_back("*");
                }
                _filters.emplace_back(match_mask, depth, uid, gid, syscalls, exeMatchValue, cmdlineFilters);
            } else {
                Logger::Error("Invalid entry (%d) in config for '%s'", idx, CONFIG_PARAM_NAME.c_str());
                _filters.clear();
                return false;
            }
        }
    }
    return true;
}