1 //--------------------------------------------------------------------------
2 // Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3 // Copyright (C) 2008-2013 Sourcefire, Inc.
4 //
5 // This program is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License Version 2 as published
7 // by the Free Software Foundation.  You may not use, modify or distribute
8 // this program under any other version of the GNU General Public License.
9 //
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 //--------------------------------------------------------------------------
19 
20 #ifndef TREENODES_H
21 #define TREENODES_H
22 
23 // rule header (RTN) and body (OTN) nodes
24 
25 #include "actions/actions.h"
26 #include "detection/signature.h"
27 #include "detection/rule_option_types.h"
28 #include "main/policy.h"
29 #include "main/snort_types.h"
30 #include "ports/port_group.h"
31 #include "time/clock_defs.h"
32 
33 namespace snort
34 {
35 class IpsOption;
36 struct Packet;
37 }
38 struct RuleTreeNode;
39 struct PortObject;
40 struct OutputSet;
41 struct TagData;
42 struct sfip_var_t;
43 
44 /* same as the rule header FP list */
45 struct OptFpList
46 {
47     snort::IpsOption* ips_opt;
48 
49     int (* OptTestFunc)(void* option_data, class Cursor&, snort::Packet*);
50 
51     OptFpList* next;
52 
53     unsigned char isRelative;
54     option_type_t type;
55 };
56 
57 struct OtnState
58 {
59     // profiling
60     // FIXIT-L factor the profiling stuff out
61     hr_duration elapsed = 0_ticks;
62     hr_duration elapsed_match = 0_ticks;
63     hr_duration elapsed_no_match = 0_ticks;
64 
65     uint64_t checks = 0;
66     uint64_t matches = 0;
67     uint8_t noalerts = 0;
68     uint64_t alerts = 0;
69 
70     uint64_t latency_timeouts = 0;
71     uint64_t latency_suspends = 0;
72 
73     operator bool() const
74     { return elapsed > 0_ticks || checks > 0; }
75 };
76 
77 /* function pointer list for rule head nodes */
78 // FIXIT-L use bit mask to determine what header checks to do
79 // cheaper than traversing a list and uses much less memory
80 struct RuleFpList
81 {
82     /* context data for this test */
83     void* context = nullptr;
84 
85     /* rule check function pointer */
86     int (* RuleHeadFunc)(snort::Packet*, RuleTreeNode*, RuleFpList*, int) = nullptr;
87 
88     /* pointer to the next rule function node */
89     RuleFpList* next = nullptr;
90 };
91 
92 struct RuleHeader
93 {
RuleHeaderRuleHeader94     RuleHeader(const char* s) : action(s) { }
95 
96     std::string action;
97     std::string proto;
98     std::string src_nets;
99     std::string src_ports;
100     std::string dir;
101     std::string dst_nets;
102     std::string dst_ports;
103 };
104 
105 // one of these per rule per policy
106 // represents head part of rule
107 struct RuleTreeNode
108 {
109     using Flag = uint8_t;
110     static constexpr Flag ENABLED       = 0x01;
111     static constexpr Flag ANY_SRC_PORT  = 0x02;
112     static constexpr Flag ANY_DST_PORT  = 0x04;
113     static constexpr Flag ANY_FLAGS     = 0x08;
114     static constexpr Flag BIDIRECTIONAL = 0x10;
115     static constexpr Flag ANY_SRC_IP    = 0x20;
116     static constexpr Flag ANY_DST_IP    = 0x40;
117     static constexpr Flag USER_MODE     = 0x80;
118 
119     RuleFpList* rule_func = nullptr; /* match functions.. (Bidirectional etc.. ) */
120     RuleHeader* header = nullptr;
121 
122     sfip_var_t* sip = nullptr;
123     sfip_var_t* dip = nullptr;
124 
125     PortObject* src_portobject = nullptr;
126     PortObject* dst_portobject = nullptr;
127 
128     struct ListHead* listhead = nullptr;
129 
130     SnortProtocolId snort_protocol_id = 0;
131 
132     // reference count from otn.
133     // Multiple OTNs can reference this RTN with the same policy.
134     unsigned int otnRefCount = 0; // FIXIT-L shared_ptr?
135 
136     Actions::Type action = 0;
137 
138     uint8_t flags = 0;
139 
set_enabledRuleTreeNode140     void set_enabled()
141     { flags |= ENABLED; }
142 
clear_enabledRuleTreeNode143     void clear_enabled()
144     { flags &= (~ENABLED); }
145 
enabledRuleTreeNode146     bool enabled() const
147     { return (flags & ENABLED) != 0; }
148 
user_modeRuleTreeNode149     bool user_mode() const
150     { return (flags & USER_MODE) != 0; }
151 
any_src_portRuleTreeNode152     bool any_src_port() const
153     { return (flags & ANY_SRC_PORT) != 0; }
154 
any_dst_portRuleTreeNode155     bool any_dst_port() const
156     { return (flags & ANY_DST_PORT) != 0; }
157 
any_any_portRuleTreeNode158     bool any_any_port() const
159     { return any_src_port() and any_dst_port(); }
160 };
161 
162 // one of these for each rule
163 // represents body part of rule
164 struct OptTreeNode
165 {
166     ~OptTreeNode();
167 
168     using Flag = uint8_t;
169     static constexpr Flag WARNED_FP  = 0x01;
170     static constexpr Flag STATELESS  = 0x02;
171     static constexpr Flag RULE_STATE = 0x04;
172     static constexpr Flag META_MATCH = 0x08;
173     static constexpr Flag TO_CLIENT  = 0x10;
174     static constexpr Flag TO_SERVER  = 0x20;
175     static constexpr Flag BIT_CHECK  = 0x40;
176 
177     /* metadata about signature */
178     SigInfo sigInfo;
179     char* soid = nullptr;
180 
181     /* plugin/detection functions go here */
182     OptFpList* opt_func = nullptr;
183     OutputSet* outputFuncs = nullptr; /* per sid enabled output functions */
184     snort::IpsOption* agent = nullptr;
185 
186     OptFpList* normal_fp_only = nullptr;
187     OptFpList* offload_fp_only = nullptr;
188 
189     struct THD_NODE* detection_filter = nullptr; /* if present, evaluated last, after header checks */
190     TagData* tag = nullptr;
191 
192     // ptr to list of RTNs (head part); indexed by policyId
193     RuleTreeNode** proto_nodes = nullptr;
194     OtnState* state = nullptr;
195 
196     unsigned evalIndex = 0;       /* where this rule sits in the evaluation sets */
197     unsigned ruleIndex = 0; // unique index
198     uint32_t num_detection_opts = 0;
199     SnortProtocolId snort_protocol_id = 0;    // Added for integrity checks during rule parsing.
200     unsigned short proto_node_num = 0;
201     uint16_t longestPatternLen = 0;
202     IpsPolicy::Enable enable;
203     Flag flags = 0;
204 
205     uint8_t sticky_buf = PM_TYPE_PKT; // parsing only
206 
set_warned_fpOptTreeNode207     void set_warned_fp()
208     { flags |= WARNED_FP; }
209 
warned_fpOptTreeNode210     bool warned_fp() const
211     { return (flags & WARNED_FP) != 0; }
212 
set_statelessOptTreeNode213     void set_stateless()
214     { flags |= STATELESS; }
215 
statelessOptTreeNode216     bool stateless() const
217     { return (flags & STATELESS) != 0; }
218 
set_enabledOptTreeNode219     void set_enabled(IpsPolicy::Enable e)
220     { enable = e; flags |= RULE_STATE; }
221 
is_rule_state_stubOptTreeNode222     bool is_rule_state_stub() const
223     { return (flags & RULE_STATE) != 0; }
224 
enabled_somewhereOptTreeNode225     bool enabled_somewhere() const
226     {
227         for ( unsigned i = 0; i < proto_node_num; i++ )
228             if ( proto_nodes[i] and proto_nodes[i]->enabled() )
229                 return true;
230 
231         return false;
232     }
233 
set_metadata_matchOptTreeNode234     void set_metadata_match()
235     { flags |= META_MATCH; }
236 
metadata_matchedOptTreeNode237     bool metadata_matched() const
238     { return (flags & META_MATCH) != 0; }
239 
set_to_clientOptTreeNode240     void set_to_client()
241     { flags |= TO_CLIENT; }
242 
to_clientOptTreeNode243     bool to_client() const
244     { return (flags & TO_CLIENT) != 0; }
245 
set_to_serverOptTreeNode246     void set_to_server()
247     { flags |= TO_SERVER; }
248 
to_serverOptTreeNode249     bool to_server() const
250     { return (flags & TO_SERVER) != 0; }
251 
set_flowbits_checkOptTreeNode252     void set_flowbits_check()
253     { flags |= BIT_CHECK; }
254 
checks_flowbitsOptTreeNode255     bool checks_flowbits() const
256     { return (flags & BIT_CHECK) != 0; }
257 
258     void update_fp(snort::IpsOption*);
259 };
260 
261 typedef int (* RuleOptEvalFunc)(void*, Cursor&, snort::Packet*);
262 OptFpList* AddOptFuncToList(RuleOptEvalFunc, OptTreeNode*);
263 
264 void* get_rule_type_data(OptTreeNode*, const char* name);
265 
266 namespace snort
267 {
268 SO_PUBLIC bool otn_has_plugin(OptTreeNode* otn, const char* name);
269 }
270 
271 bool otn_set_agent(OptTreeNode*, snort::IpsOption*);
272 
273 void otn_trigger_actions(const OptTreeNode*, snort::Packet*);
274 
275 #endif
276 
277