1 /*
2 * ModSecurity, http://www.modsecurity.org/
3 * Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/)
4 *
5 * You may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * If any of the files related to licensing are missing or if you have any
11 * other questions related to licensing please contact Trustwave Holdings, Inc.
12 * directly using the email address security@modsecurity.org.
13 *
14 */
15
16 #include "src/operators/fuzzy_hash.h"
17
18 #include <string>
19
20 #include "src/operators/operator.h"
21 #include "src/utils/system.h"
22
23 namespace modsecurity {
24 namespace operators {
25
init(const std::string & param2,std::string * error)26 bool FuzzyHash::init(const std::string ¶m2, std::string *error) {
27 #ifdef WITH_SSDEEP
28 std::string digit;
29 std::string file;
30 std::istream *iss;
31 struct fuzzy_hash_chunk *chunk, *t;
32 std::string err;
33
34 auto pos = m_param.find_last_of(' ');
35 if (pos == std::string::npos) {
36 error->assign("Please use @fuzzyHash with filename and value");
37 return false;
38 }
39 digit.append(std::string(m_param, pos+1));
40 file.append(std::string(m_param, 0, pos));
41 try {
42 m_threshold = std::stoi(digit);
43 } catch (...) {
44 error->assign("Expecting a digit, got: " + digit);
45 return false;
46 }
47
48 std::string resource = utils::find_resource(file, param2, &err);
49 iss = new std::ifstream(resource, std::ios::in);
50
51 if (((std::ifstream *)iss)->is_open() == false) {
52 error->assign("Failed to open file: " + m_param + ". " + err);
53 delete iss;
54 return false;
55 }
56
57 for (std::string line; std::getline(*iss, line); ) {
58 chunk = (struct fuzzy_hash_chunk *)calloc(1,
59 sizeof(struct fuzzy_hash_chunk));
60
61 chunk->data = strdup(line.c_str());
62 chunk->next = NULL;
63
64 if (m_head == NULL) {
65 m_head = chunk;
66 } else {
67 t = m_head;
68
69 while (t->next) {
70 t = t->next;
71 }
72
73 t->next = chunk;
74 }
75 }
76
77 delete iss;
78 return true;
79 #else
80 error->assign("@fuzzyHash: SSDEEP support was not enabled " \
81 "during the compilation.");
82 return false;
83 #endif
84 }
85
~FuzzyHash()86 FuzzyHash::~FuzzyHash() {
87 struct fuzzy_hash_chunk *c = m_head;
88 while (c) {
89 struct fuzzy_hash_chunk *t = c;
90 free(c->data);
91 c->data = NULL;
92 c = c->next;
93 free(t);
94 }
95 m_head = NULL;
96 }
97
98
evaluate(Transaction * t,const std::string & str)99 bool FuzzyHash::evaluate(Transaction *t, const std::string &str) {
100 #ifdef WITH_SSDEEP
101 char result[FUZZY_MAX_RESULT];
102 struct fuzzy_hash_chunk *chunk = m_head;
103
104 if (fuzzy_hash_buf((const unsigned char*)str.c_str(),
105 str.size(), result)) {
106 ms_dbg_a(t, 4, "Problems generating fuzzy hash");
107 return false;
108 }
109
110 while (chunk != NULL) {
111 int i = fuzzy_compare(chunk->data, result);
112 if (i >= m_threshold) {
113 ms_dbg_a(t, 4, "Fuzzy hash: matched " \
114 "with score: " + std::to_string(i) + ".");
115 return true;
116 }
117 chunk = chunk->next;
118 }
119 #endif
120 /* No match. */
121 return false;
122 }
123
124 } // namespace operators
125 } // namespace modsecurity
126