1 /* $Id$ */
2 /*
3 ** Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
4 ** Copyright (C) 2002-2013 Sourcefire, Inc.
5 ** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
6 **
7 ** This program is free software; you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License Version 2 as
9 ** published by the Free Software Foundation.  You may not use, modify or
10 ** distribute this program under any other version of the GNU General
11 ** Public License.
12 **
13 ** This program is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ** GNU General Public License for more details.
17 **
18 ** You should have received a copy of the GNU General Public License
19 ** along with this program; if not, write to the Free Software
20 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 */
22 
23 #ifndef __SP_PATTERN_MATCH_H__
24 #define __SP_PATTERN_MATCH_H__
25 
26 #include <ctype.h>
27 
28 #include "snort.h"
29 #include "snort_debug.h"
30 #include "rules.h" /* needed for OptTreeNode defintion */
31 #include "treenodes.h"
32 #include "detection_util.h"
33 #include "hashstring.h"
34 
35 /********************************************************************
36  * Macros
37  ********************************************************************/
38 #define CHECK_AND_PATTERN_MATCH 1
39 #define CHECK_URI_PATTERN_MATCH 2
40 #define PMD_WITHIN_UNDEFINED ((unsigned) -1)
41 
42 /********************************************************************
43  * Data structures
44  ********************************************************************/
45 typedef struct _PatternMatchData
46 {
47     int offset;             /* pattern search start offset */
48     int depth;              /* pattern search depth */
49 
50     int distance;           /* offset to start from based on last match */
51     u_int within;           /* this pattern must be found
52                                within X bytes of last match*/
53 
54     int8_t offset_var;      /* byte_extract variable indices for offset, */
55     int8_t depth_var;       /* depth, distance, within */
56     int8_t distance_var;
57     int8_t within_var;
58 
59     int rawbytes;           /* Search the raw bytes rather than any decoded app
60                                buffer */
61     int replace_depth;      /* >=0 is offset to start of replace */
62 
63     int nocase;             /* Toggle case insensitity */
64     int use_doe;            /* Use the doe_ptr for relative pattern searching */
65     HTTP_BUFFER http_buffer;/* Index of the URI buffer */
66     int buffer_func;        /* buffer function CheckAND or CheckUri */
67     u_int pattern_size;     /* size of app layer pattern */
68     u_int replace_size;     /* size of app layer replace pattern */
69     char *replace_buf;      /* app layer pattern to replace with */
70     char *pattern_buf;      /* app layer pattern to match on */
71     int (*search)(const char *, int, struct _PatternMatchData *);  /* search function */
72     int *skip_stride; /* B-M skip array */
73     int *shift_stride; /* B-M shift array */
74     u_int pattern_max_jump_size; /* Maximum distance we can jump to search for
75                                   * this pattern again. */
76     OptFpList *fpl;         /* Pointer to the OTN FPList for this pattern */
77                             /* Needed to be able to set the isRelative flag */
78 
79     /* Set if fast pattern matcher found a content in the packet,
80        but the rule option specifies a negated content. Only
81        applies to negative contents that are not relative */
82     struct
83     {
84         struct timeval ts;
85         uint64_t packet_number;
86         uint32_t rebuild_flag;
87 
88     } last_check;
89 
90     /* For fast_pattern arguments */
91     uint8_t fp;
92     uint8_t fp_only;
93     uint16_t fp_offset;
94     uint16_t fp_length;
95 
96     uint8_t exception_flag; /* search for "not this pattern" */
97 
98     /* Used in ds_list - do not try to iterate after parsing a rule
99      * since the detection option tree will eliminate duplicates and
100      * the list may have missing pmds */
101     struct _PatternMatchData *prev; /* ptr to previous match struct */
102     struct _PatternMatchData *next; /* ptr to next match struct */
103 
104     Secure_Hash_Type pattern_type;
105     int protected_length;
106     bool protected_pattern;
107 } PatternMatchData;
108 
109 /********************************************************************
110  * Public function prototypes
111  ********************************************************************/
112 void SetupPatternMatch(void);
113 PatternMatchData * NewNode(OptTreeNode *, int);
114 void PatternMatchFree(void *d);
115 uint32_t PatternMatchHash(void *d);
116 int PatternMatchCompare(void *l, void *r);
117 void FinalizeContentUniqueness(struct _SnortConfig *sc, OptTreeNode *otn);
118 void ValidateFastPattern(OptTreeNode *otn);
119 void make_precomp(PatternMatchData *);
120 void ParsePattern(char *, OptTreeNode *, int);
121 void ParseProtectedPattern(char *, OptTreeNode *, int);
122 int uniSearchCI(const char *, int, PatternMatchData *);
123 int CheckANDPatternMatch(void *, Packet *);
124 int CheckUriPatternMatch(void *, Packet *);
125 void PatternMatchDuplicatePmd(void *, PatternMatchData *);
126 int PatternMatchAdjustRelativeOffsets(PatternMatchData *orig_pmd, PatternMatchData *dup_pmd,
127         const uint8_t *current_cursor, const uint8_t *orig_cursor);
128 
129 #if 0
130 /* Not implemented */
131 int CheckORPatternMatch(Packet *, OptTreeNode *, OptFpList *);
132 #endif
133 
IsHttpBufFpEligible(HTTP_BUFFER http_buffer)134 static inline bool IsHttpBufFpEligible (HTTP_BUFFER http_buffer)
135 {
136     switch ( http_buffer )
137     {
138     case HTTP_BUFFER_URI:
139     case HTTP_BUFFER_HEADER:
140     case HTTP_BUFFER_CLIENT_BODY:
141         return true;
142     default:
143         break;
144     }
145     return false;
146 }
147 
RemovePmdFromList(PatternMatchData * pmd)148 static inline PatternMatchData * RemovePmdFromList(PatternMatchData *pmd)
149 {
150     if (pmd == NULL)
151         return NULL;
152 
153     if (pmd->prev)
154         pmd->prev->next = pmd->next;
155     if (pmd->next)
156         pmd->next->prev = pmd->prev;
157 
158     pmd->next = NULL;
159     pmd->prev = NULL;
160 
161     return pmd;
162 }
163 
InsertPmdAtFront(PatternMatchData ** head,PatternMatchData * ins)164 static inline int InsertPmdAtFront(PatternMatchData **head, PatternMatchData *ins)
165 {
166     if (head == NULL)
167         return -1;
168 
169     if (ins == NULL)
170         return 0;
171 
172     ins->next = *head;
173     if (*head != NULL)
174         (*head)->prev = ins;
175     *head = ins;
176 
177     return 0;
178 }
179 
AppendPmdToList(PatternMatchData ** head,PatternMatchData * ins)180 static inline int AppendPmdToList(PatternMatchData **head, PatternMatchData *ins)
181 {
182     PatternMatchData *tmp;
183 
184     if (head == NULL)
185         return -1;
186 
187     if (ins == NULL)
188         return 0;
189 
190     if (*head == NULL)
191     {
192         *head = ins;
193         ins->prev = NULL;
194         return 0;
195     }
196 
197     for (tmp = *head; tmp->next != NULL; tmp = tmp->next);
198     tmp->next = ins;
199     ins->prev = tmp;
200 
201     return 0;
202 }
203 
204 
FreePmdList(PatternMatchData * pmd_list)205 static inline void FreePmdList(PatternMatchData *pmd_list)
206 {
207     if (pmd_list == NULL)
208         return;
209 
210     while (pmd_list != NULL)
211     {
212         PatternMatchData *tmp = pmd_list->next;
213         PatternMatchFree((void *)pmd_list);
214         pmd_list = tmp;
215     }
216 }
217 
218 #endif /* __SP_PATTERN_MATCH_H__ */
219