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/validate_byte_range.h"
17
18 #include <string>
19 #include <memory>
20
21 #include "src/operators/operator.h"
22
23 namespace modsecurity {
24 namespace operators {
25
getRange(const std::string & rangeRepresentation,std::string * error)26 bool ValidateByteRange::getRange(const std::string &rangeRepresentation,
27 std::string *error) {
28 size_t pos = rangeRepresentation.find_first_of("-");
29 int start;
30 int end;
31
32 if (pos == std::string::npos) {
33 try {
34 start = std::stoi(rangeRepresentation);
35 } catch(...) {
36 error->assign("Not able to convert '" + rangeRepresentation +
37 "' into a number");
38 return false;
39 }
40 table[start >> 3] = (table[start >> 3] | (1 << (start & 0x7)));
41 return true;
42 }
43
44 try {
45 start = std::stoi(std::string(rangeRepresentation, 0, pos));
46 } catch (...) {
47 error->assign("Not able to convert '" +
48 std::string(rangeRepresentation, 0, pos) +
49 "' into a number");
50 return false;
51 }
52
53 try {
54 end = std::stoi(std::string(rangeRepresentation, pos + 1,
55 rangeRepresentation.length() - (pos + 1)));
56 } catch (...) {
57 error->assign("Not able to convert '" + std::string(rangeRepresentation,
58 pos + 1, rangeRepresentation.length() - (pos + 1)) +
59 "' into a number");
60 return false;
61 }
62
63 if ((start < 0) || (start > 255)) {
64 error->assign("Invalid range start value: " +
65 std::to_string(start));
66 return false;
67 }
68 if ((end < 0) || (end > 255)) {
69 error->assign("Invalid range end value: " + std::to_string(end));
70 return false;
71 }
72 if (start > end) {
73 error->assign("Invalid range: " + std::to_string(start) + "-" +
74 std::to_string(end));
75 return false;
76 }
77
78 while (start <= end) {
79 table[start >> 3] = (table[start >> 3] | (1 << (start & 0x7)));
80 start++;
81 }
82
83 return true;
84 }
85
86
init(const std::string & file,std::string * error)87 bool ValidateByteRange::init(const std::string &file,
88 std::string *error) {
89 size_t pos = m_param.find_first_of(",");
90
91 if (pos == std::string::npos) {
92 getRange(m_param, error);
93 } else {
94 getRange(std::string(m_param, 0, pos), error);
95 }
96
97 while (pos != std::string::npos) {
98 size_t next_pos = m_param.find_first_of(",", pos + 1);
99
100 if (next_pos == std::string::npos) {
101 getRange(std::string(m_param, pos + 1, m_param.length() -
102 (pos + 1)), error);
103 } else {
104 getRange(std::string(m_param, pos + 1, next_pos - (pos + 1)), error);
105 }
106 pos = next_pos;
107 }
108
109 return true;
110 }
111
112
evaluate(Transaction * transaction,RuleWithActions * rule,const std::string & input,std::shared_ptr<RuleMessage> ruleMessage)113 bool ValidateByteRange::evaluate(Transaction *transaction, RuleWithActions *rule,
114 const std::string &input, std::shared_ptr<RuleMessage> ruleMessage) {
115 bool ret = true;
116
117 size_t count = 0;
118 for (int i = 0; i < input.length(); i++) {
119 int x = (unsigned char) input.at(i);
120 if (!(table[x >> 3] & (1 << (x & 0x7)))) {
121 // debug(9, "Value " + std::to_string(x) + " in " +
122 // input + " ouside range: " + param);
123 logOffset(ruleMessage, i, 1);
124 count++;
125 }
126 }
127
128 ret = (count != 0);
129
130 // debug(9, "Found %d byte(s) in %s outside range: %s.",
131 // count, var->name, rule->op_param);
132
133 return ret;
134 }
135
136
137 } // namespace operators
138 } // namespace modsecurity
139