1 //--------------------------------------------------------------------------
2 // Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3 // Copyright (C) 2002-2013 Sourcefire, Inc.
4 // Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
5 //
6 // This program is free software; you can redistribute it and/or modify it
7 // under the terms of the GNU General Public License Version 2 as published
8 // by the Free Software Foundation.  You may not use, modify or distribute
9 // this program under any other version of the GNU General Public License.
10 //
11 // This program is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License along
17 // with this program; if not, write to the Free Software Foundation, Inc.,
18 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 //--------------------------------------------------------------------------
20 
21 #ifndef PATTERN_MATCH_DATA_H
22 #define PATTERN_MATCH_DATA_H
23 
24 #include <sys/time.h>
25 #include <vector>
26 
27 #include "framework/ips_option.h"  // FIXIT-L not a good dependency
28 
29 struct PmdLastCheck
30 {
31     struct timeval ts;
32     uint64_t context_num;
33     uint32_t rebuild_flag;
34     uint16_t run_num;
35 };
36 
37 struct PatternMatchData
38 {
39     const char* pattern_buf; // app layer pattern to match on
40 
41     // FIXIT-L wasting some memory here:
42     // - this is not used by content option logic directly
43     // - and only used on current eval (not across packets)
44     // (partly mitigated by only allocating if exception_flag is set)
45     //
46     /* Set if fast pattern matcher found a content in the packet,
47        but the rule option specifies a negated content. Only
48        applies to negative contents that are not relative */
49     PmdLastCheck* last_check;
50 
51     unsigned pattern_size;   // size of app layer pattern
52 
53     int offset;              // pattern search start offset
54     int depth;               // pattern search depth
55 
56     enum
57     {
58         NEGATED  = 0x01,
59         NO_CASE  = 0x02,
60         RELATIVE = 0x04,
61         LITERAL  = 0x08,
62         FAST_PAT = 0x10,
63         NO_FP    = 0x20,
64     };
65 
66     uint16_t flags;          // from above enum
67     uint16_t mpse_flags;     // passed through to mpse
68 
69     uint16_t fp_offset;
70     uint16_t fp_length;
71 
72     // not used by ips_content
73     uint8_t pm_type;
74 
is_unboundedPatternMatchData75     bool is_unbounded() const
76     { return !depth; }
77 
set_fast_patternPatternMatchData78     void set_fast_pattern()
79     { flags |= FAST_PAT; }
80 
set_negatedPatternMatchData81     void set_negated()
82     { flags |= NEGATED; }
83 
set_no_casePatternMatchData84     void set_no_case()
85     { flags |= NO_CASE; }
86 
set_relativePatternMatchData87     void set_relative()
88     { flags |= RELATIVE; }
89 
set_literalPatternMatchData90     void set_literal()
91     { flags |= LITERAL; }
92 
is_fast_patternPatternMatchData93     bool is_fast_pattern() const
94     { return (flags & FAST_PAT) != 0; }
95 
is_negatedPatternMatchData96     bool is_negated() const
97     { return (flags & NEGATED) != 0; }
98 
is_no_casePatternMatchData99     bool is_no_case() const
100     { return (flags & NO_CASE) != 0; }
101 
is_relativePatternMatchData102     bool is_relative() const
103     { return (flags & RELATIVE) != 0; }
104 
is_literalPatternMatchData105     bool is_literal() const
106     { return (flags & LITERAL) != 0; }
107 
108     bool can_be_fp() const;
109 };
110 
111 typedef std::vector<PatternMatchData*> PatternMatchVector;
112 
can_be_fp()113 inline bool PatternMatchData::can_be_fp() const
114 {
115     if ( !pattern_buf or !pattern_size )
116         return false;
117 
118     if ( flags & NO_FP )
119         return false;
120 
121     if ( !is_negated() )
122         return true;
123 
124     // Negative contents can only be considered if they are not
125     // relative and don't have any offset or depth.  This is because
126     // the pattern matcher does not take these into consideration and
127     // may find the content in a non-relevant section of the payload
128     // and thus disable the rule when it shouldn't be.
129 
130     // Also case sensitive patterns cannot be considered since patterns
131     // are inserted into the pattern matcher without case which may
132     // lead to false negatives.
133 
134     if ( is_relative() or !is_no_case() or offset or depth )
135         return false;
136 
137     return true;
138 }
139 
140 #endif
141 
142