mirror of
https://github.com/openappsec/openappsec.git
synced 2025-10-01 20:17:43 +03:00
First release of open-appsec source code
This commit is contained in:
165
components/utils/pm/pm_hook.cc
Normal file
165
components/utils/pm/pm_hook.cc
Normal file
@@ -0,0 +1,165 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "pm_hook.h"
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include "kiss_patterns.h"
|
||||
#include "kiss_thin_nfa_impl.h"
|
||||
#include "sasal.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
SASAL_START // Multiple Pattern Matcher
|
||||
USE_DEBUG_FLAG(D_PM_COMP);
|
||||
USE_DEBUG_FLAG(D_PM_EXEC);
|
||||
USE_DEBUG_FLAG(D_PM);
|
||||
|
||||
static int
|
||||
pm_pattern_to_kiss_pat_flags(const PMPattern &pat)
|
||||
{
|
||||
int kiss_pat_flags = 0;
|
||||
if (pat.isStartMatch()) {
|
||||
kiss_pat_flags |= KISS_PM_LSS_AT_BUF_START;
|
||||
}
|
||||
if (pat.isEndMatch()) {
|
||||
kiss_pat_flags |= KISS_PM_LSS_AT_BUF_END;
|
||||
}
|
||||
return kiss_pat_flags;
|
||||
}
|
||||
|
||||
|
||||
static list<kiss_pmglob_string_s>
|
||||
convert_patt_map_to_kiss_list(const map<int, PMPattern> &patt_map)
|
||||
{
|
||||
list<kiss_pmglob_string_s> kiss_pats;
|
||||
for (auto &pair : patt_map) {
|
||||
auto &id = pair.first;
|
||||
auto &pattern = pair.second;
|
||||
kiss_pats.emplace_back(pattern.data(), pattern.size(), id, pm_pattern_to_kiss_pat_flags(pattern));
|
||||
}
|
||||
return kiss_pats;
|
||||
}
|
||||
|
||||
// Explicit empty ctor and dtor needed due to incomplete definition of class used in unique_ptr. Bummer...
|
||||
PMHook::PMHook()
|
||||
{
|
||||
}
|
||||
|
||||
PMHook::~PMHook()
|
||||
{
|
||||
}
|
||||
|
||||
Maybe<PMPattern>
|
||||
PMHook::lineToPattern(const string &line)
|
||||
{
|
||||
if (line.empty()) return genError("Empty string");
|
||||
|
||||
bool start = (*line.begin()) == '^';
|
||||
bool end = (*line.rbegin()) == '$';
|
||||
|
||||
int start_offset = start ? 1 : 0;
|
||||
int line_size = line.size() - (start ? 1 : 0) - (end ? 1 : 0);
|
||||
auto clean_line = line.substr(start_offset, line_size);
|
||||
|
||||
if (clean_line.empty()) return genError("Pattern must contain actual content");
|
||||
|
||||
return PMPattern(clean_line, start, end);
|
||||
}
|
||||
|
||||
Maybe<void>
|
||||
PMHook::prepare(const set<PMPattern> &inputs)
|
||||
{
|
||||
map<int, PMPattern> tmp;
|
||||
int index = 0;
|
||||
for (auto &pat : inputs) {
|
||||
tmp.emplace(++index, pat);
|
||||
}
|
||||
|
||||
if (Debug::isFlagAtleastLevel(D_PM_COMP, Debug::DebugLevel::DEBUG)) kiss_debug_start();
|
||||
KissPMError pm_err;
|
||||
handle = kiss_thin_nfa_compile(convert_patt_map_to_kiss_list(tmp), KISS_PM_COMP_CASELESS, &pm_err);
|
||||
if (Debug::isFlagAtleastLevel(D_PM_COMP, Debug::DebugLevel::DEBUG)) kiss_debug_stop();
|
||||
|
||||
if (handle == nullptr) {
|
||||
dbgError(D_PM_COMP) << "PMHook::prepare() failed" << pm_err;
|
||||
return genError(pm_err.error_string);
|
||||
}
|
||||
|
||||
patterns = tmp;
|
||||
return Maybe<void>();
|
||||
}
|
||||
|
||||
|
||||
set<PMPattern>
|
||||
PMHook::scanBuf(const Buffer &buf) const
|
||||
{
|
||||
dbgAssert(handle != nullptr) << "Unusable Pattern Matcher";
|
||||
|
||||
vector<pair<uint, uint>> pm_matches;
|
||||
kiss_thin_nfa_exec(handle.get(), buf, pm_matches);
|
||||
dbgTrace(D_PM) << pm_matches.size() << " raw matches found";
|
||||
|
||||
set<PMPattern> res;
|
||||
for (auto &match : pm_matches) {
|
||||
res.insert(patterns.at(match.first));
|
||||
}
|
||||
dbgTrace(D_PM) << res.size() << " matches found after removing the duplicates";
|
||||
return res;
|
||||
}
|
||||
|
||||
set<pair<uint, PMPattern>>
|
||||
PMHook::scanBufWithOffset(const Buffer &buf) const
|
||||
{
|
||||
dbgAssert(handle != nullptr) << "Unusable Pattern Matcher";
|
||||
|
||||
vector<pair<uint, uint>> pm_matches;
|
||||
kiss_thin_nfa_exec(handle.get(), buf, pm_matches);
|
||||
dbgTrace(D_PM) << pm_matches.size() << " raw matches found";
|
||||
|
||||
set<pair<uint, PMPattern>> res;
|
||||
for (auto &match : pm_matches) {
|
||||
res.emplace(match.second, patterns.at(match.first));
|
||||
}
|
||||
dbgTrace(D_PM) << res.size() << " matches found";
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
PMHook::scanBufWithOffsetLambda(const Buffer &buf, function<void(uint, const PMPattern&)> cb) const
|
||||
{
|
||||
|
||||
for (auto &res : scanBufWithOffset(buf)) {
|
||||
cb(res.first, res.second);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
PMPattern::operator<(const PMPattern &other) const
|
||||
{
|
||||
if (pattern != other.pattern) return pattern < other.pattern;
|
||||
if (index != other.index) return index < other.index;
|
||||
return tie(match_start, match_end) < tie(other.match_start, other.match_end);
|
||||
}
|
||||
bool
|
||||
PMPattern::operator==(const PMPattern &other) const
|
||||
{
|
||||
return
|
||||
index == other.index &&
|
||||
pattern == other.pattern &&
|
||||
match_start == other.match_start &&
|
||||
match_end == other.match_end;
|
||||
}
|
||||
SASAL_END
|
Reference in New Issue
Block a user