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