/src/suricata7/src/detect-depth.c
Line | Count | Source |
1 | | /* Copyright (C) 2007-2019 Open Information Security Foundation |
2 | | * |
3 | | * You can copy, redistribute or modify this Program under the terms of |
4 | | * the GNU General Public License version 2 as published by the Free |
5 | | * Software Foundation. |
6 | | * |
7 | | * This program is distributed in the hope that it will be useful, |
8 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | | * GNU General Public License for more details. |
11 | | * |
12 | | * You should have received a copy of the GNU General Public License |
13 | | * version 2 along with this program; if not, write to the Free Software |
14 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
15 | | * 02110-1301, USA. |
16 | | */ |
17 | | |
18 | | /** |
19 | | * \file |
20 | | * |
21 | | * \author Victor Julien <victor@inliniac.net> |
22 | | * \author Anoop Saldanha <anoopsaldanha@gmail.com> |
23 | | * |
24 | | * Implements the depth keyword. |
25 | | */ |
26 | | |
27 | | #include "suricata-common.h" |
28 | | |
29 | | #include "decode.h" |
30 | | |
31 | | #include "detect.h" |
32 | | #include "detect-parse.h" |
33 | | #include "detect-content.h" |
34 | | #include "detect-uricontent.h" |
35 | | #include "detect-byte.h" |
36 | | #include "detect-byte-extract.h" |
37 | | #include "detect-depth.h" |
38 | | |
39 | | #include "flow-var.h" |
40 | | #include "app-layer.h" |
41 | | |
42 | | #include "util-byte.h" |
43 | | #include "util-debug.h" |
44 | | |
45 | | static int DetectDepthSetup (DetectEngineCtx *, Signature *, const char *); |
46 | | static int DetectStartsWithSetup (DetectEngineCtx *, Signature *, const char *); |
47 | | |
48 | | void DetectDepthRegister (void) |
49 | 73 | { |
50 | 73 | sigmatch_table[DETECT_DEPTH].name = "depth"; |
51 | 73 | sigmatch_table[DETECT_DEPTH].desc = "designate how many bytes from the beginning of the payload will be checked"; |
52 | 73 | sigmatch_table[DETECT_DEPTH].url = "/rules/payload-keywords.html#depth"; |
53 | 73 | sigmatch_table[DETECT_DEPTH].Match = NULL; |
54 | 73 | sigmatch_table[DETECT_DEPTH].Setup = DetectDepthSetup; |
55 | 73 | sigmatch_table[DETECT_DEPTH].Free = NULL; |
56 | | |
57 | 73 | sigmatch_table[DETECT_STARTS_WITH].name = "startswith"; |
58 | 73 | sigmatch_table[DETECT_STARTS_WITH].desc = "pattern must be at the start of a buffer (same as 'depth:<pattern len>')"; |
59 | 73 | sigmatch_table[DETECT_STARTS_WITH].url = "/rules/payload-keywords.html#startswith"; |
60 | 73 | sigmatch_table[DETECT_STARTS_WITH].Setup = DetectStartsWithSetup; |
61 | 73 | sigmatch_table[DETECT_STARTS_WITH].flags |= SIGMATCH_NOOPT; |
62 | 73 | } |
63 | | |
64 | | static int DetectDepthSetup (DetectEngineCtx *de_ctx, Signature *s, const char *depthstr) |
65 | 77.5k | { |
66 | 77.5k | const char *str = depthstr; |
67 | 77.5k | SigMatch *pm = NULL; |
68 | 77.5k | int ret = -1; |
69 | | |
70 | | /* retrieve the sm to apply the depth against */ |
71 | 77.5k | pm = DetectGetLastSMFromLists(s, DETECT_CONTENT, -1); |
72 | 77.5k | if (pm == NULL) { |
73 | 1.18k | SCLogError("depth needs " |
74 | 1.18k | "preceding content, uricontent option, http_client_body, " |
75 | 1.18k | "http_server_body, http_header option, http_raw_header option, " |
76 | 1.18k | "http_method option, http_cookie, http_raw_uri, " |
77 | 1.18k | "http_stat_msg, http_stat_code, http_user_agent, " |
78 | 1.18k | "http_host, http_raw_host or " |
79 | 1.18k | "file_data/dce_stub_data sticky buffer options."); |
80 | 1.18k | goto end; |
81 | 1.18k | } |
82 | | |
83 | | /* verify other conditions. */ |
84 | 76.3k | DetectContentData *cd = (DetectContentData *)pm->ctx; |
85 | | |
86 | 76.3k | if (cd->flags & DETECT_CONTENT_DEPTH) { |
87 | 759 | SCLogError("can't use multiple depths for the same content."); |
88 | 759 | goto end; |
89 | 759 | } |
90 | 75.5k | if ((cd->flags & DETECT_CONTENT_WITHIN) || (cd->flags & DETECT_CONTENT_DISTANCE)) { |
91 | 900 | SCLogError("can't use a relative " |
92 | 900 | "keyword like within/distance with a absolute " |
93 | 900 | "relative keyword like depth/offset for the same " |
94 | 900 | "content."); |
95 | 900 | goto end; |
96 | 900 | } |
97 | 74.6k | if (cd->flags & DETECT_CONTENT_NEGATED && cd->flags & DETECT_CONTENT_FAST_PATTERN) { |
98 | 2 | SCLogError("can't have a relative " |
99 | 2 | "negated keyword set along with 'fast_pattern'."); |
100 | 2 | goto end; |
101 | 2 | } |
102 | 74.6k | if (cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { |
103 | 2 | SCLogError("can't have a relative " |
104 | 2 | "keyword set along with 'fast_pattern:only;'."); |
105 | 2 | goto end; |
106 | 2 | } |
107 | 74.6k | if (str[0] != '-' && isalpha((unsigned char)str[0])) { |
108 | 7.26k | DetectByteIndexType index; |
109 | 7.26k | if (!DetectByteRetrieveSMVar(str, s, &index)) { |
110 | 2.25k | SCLogError("unknown byte_ keyword var " |
111 | 2.25k | "seen in depth - %s.", |
112 | 2.25k | str); |
113 | 2.25k | goto end; |
114 | 2.25k | } |
115 | 5.00k | cd->depth = index; |
116 | 5.00k | cd->flags |= DETECT_CONTENT_DEPTH_VAR; |
117 | 67.3k | } else { |
118 | 67.3k | if (StringParseUint16(&cd->depth, 0, 0, str) < 0) |
119 | 645 | { |
120 | 645 | SCLogError("invalid value for depth: %s.", str); |
121 | 645 | goto end; |
122 | 645 | } |
123 | | |
124 | 66.7k | if (cd->depth < cd->content_len) { |
125 | 956 | SCLogError("depth:%u smaller than " |
126 | 956 | "content of len %u.", |
127 | 956 | cd->depth, cd->content_len); |
128 | 956 | return -1; |
129 | 956 | } |
130 | | /* Now update the real limit, as depth is relative to the offset */ |
131 | 65.7k | cd->depth += cd->offset; |
132 | 65.7k | } |
133 | 70.7k | cd->flags |= DETECT_CONTENT_DEPTH; |
134 | | |
135 | 70.7k | ret = 0; |
136 | 76.5k | end: |
137 | 76.5k | return ret; |
138 | 70.7k | } |
139 | | |
140 | | static int DetectStartsWithSetup (DetectEngineCtx *de_ctx, Signature *s, const char *unused) |
141 | 24.7k | { |
142 | 24.7k | SigMatch *pm = NULL; |
143 | 24.7k | int ret = -1; |
144 | | |
145 | | /* retrieve the sm to apply the depth against */ |
146 | 24.7k | pm = DetectGetLastSMFromLists(s, DETECT_CONTENT, -1); |
147 | 24.7k | if (pm == NULL) { |
148 | 187 | SCLogError("startswith needs a " |
149 | 187 | "preceding content option."); |
150 | 187 | goto end; |
151 | 187 | } |
152 | | |
153 | | /* verify other conditions. */ |
154 | 24.5k | DetectContentData *cd = (DetectContentData *)pm->ctx; |
155 | | |
156 | 24.5k | if (cd->flags & DETECT_CONTENT_DEPTH) { |
157 | 43 | SCLogError("can't use multiple " |
158 | 43 | "depth/startswith settings for the same content."); |
159 | 43 | goto end; |
160 | 43 | } |
161 | 24.4k | if ((cd->flags & DETECT_CONTENT_WITHIN) || (cd->flags & DETECT_CONTENT_DISTANCE)) { |
162 | 233 | SCLogError("can't use a relative " |
163 | 233 | "keyword like within/distance with a absolute " |
164 | 233 | "relative keyword like depth/offset for the same " |
165 | 233 | "content."); |
166 | 233 | goto end; |
167 | 233 | } |
168 | 24.2k | if (cd->flags & DETECT_CONTENT_NEGATED && cd->flags & DETECT_CONTENT_FAST_PATTERN) { |
169 | 3 | SCLogError("can't have a relative " |
170 | 3 | "negated keyword set along with a 'fast_pattern'."); |
171 | 3 | goto end; |
172 | 3 | } |
173 | 24.2k | if (cd->flags & DETECT_CONTENT_FAST_PATTERN_ONLY) { |
174 | 4 | SCLogError("can't have a relative " |
175 | 4 | "keyword set along with 'fast_pattern:only;'."); |
176 | 4 | goto end; |
177 | 4 | } |
178 | 24.2k | if (cd->flags & DETECT_CONTENT_OFFSET) { |
179 | 4 | SCLogError("can't mix offset " |
180 | 4 | "with startswith."); |
181 | 4 | goto end; |
182 | 4 | } |
183 | | |
184 | 24.2k | cd->depth = cd->content_len; |
185 | 24.2k | cd->flags |= DETECT_CONTENT_DEPTH; |
186 | 24.2k | cd->flags |= DETECT_CONTENT_STARTS_WITH; |
187 | | |
188 | 24.2k | ret = 0; |
189 | 24.7k | end: |
190 | 24.7k | return ret; |
191 | 24.2k | } |