/src/suricata8/src/detect-engine-buffer.c
Line | Count | Source |
1 | | /* Copyright (C) 2025 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 | | */ |
23 | | |
24 | | #include "suricata-common.h" |
25 | | #include "detect-engine.h" |
26 | | #include "detect-parse.h" |
27 | | #include "detect-engine-buffer.h" |
28 | | |
29 | | int SCDetectBufferSetActiveList(DetectEngineCtx *de_ctx, Signature *s, const int list) |
30 | 577k | { |
31 | 577k | BUG_ON(s->init_data == NULL); |
32 | | |
33 | 577k | if (s->init_data->list == DETECT_SM_LIST_BASE64_DATA) { |
34 | 13 | SCLogError("Rule buffer cannot be reset after base64_data."); |
35 | 13 | return -1; |
36 | 13 | } |
37 | | |
38 | 577k | if (s->init_data->list && s->init_data->transforms.cnt) { |
39 | 2.88k | SCLogError("no matches following transform(s)"); |
40 | 2.88k | return -1; |
41 | 2.88k | } |
42 | 574k | s->init_data->list = list; |
43 | 574k | s->init_data->list_set = true; |
44 | | |
45 | | // check if last has matches -> if no, error |
46 | 574k | if (s->init_data->curbuf && s->init_data->curbuf->head == NULL) { |
47 | 2.75k | SCLogError("previous sticky buffer has no matches"); |
48 | 2.75k | return -1; |
49 | 2.75k | } |
50 | | |
51 | 5.04M | for (uint32_t x = 0; x < s->init_data->buffers_size; x++) { |
52 | 4.50M | SignatureInitDataBuffer *b = &s->init_data->buffers[x]; |
53 | 5.58M | for (SigMatch *sm = b->head; sm != NULL; sm = sm->next) { |
54 | 1.07M | SCLogDebug( |
55 | 1.07M | "buf:%p: id:%u: '%s' pos %u", b, b->id, sigmatch_table[sm->type].name, sm->idx); |
56 | 1.07M | } |
57 | 4.50M | if ((uint32_t)list == b->id) { |
58 | 179k | SCLogDebug("found buffer %p for list %d", b, list); |
59 | 179k | if (s->init_data->buffers[x].sm_init) { |
60 | 2.45k | s->init_data->buffers[x].sm_init = false; |
61 | 2.45k | SCLogDebug("sm_init was true for %p list %d", b, list); |
62 | 2.45k | s->init_data->curbuf = b; |
63 | 2.45k | return 0; |
64 | | |
65 | 177k | } else if (DetectEngineBufferTypeSupportsMultiInstanceGetById(de_ctx, list)) { |
66 | | // fall through |
67 | 141k | } else if (!b->only_ts && (s->init_data->init_flags & SIG_FLAG_INIT_FORCE_TOSERVER)) { |
68 | | // fall through |
69 | 35.7k | } else if (!b->only_tc && (s->init_data->init_flags & SIG_FLAG_INIT_FORCE_TOCLIENT)) { |
70 | | // fall through |
71 | 35.6k | } else { |
72 | | // we create a new buffer for the same id but forced different direction |
73 | 35.6k | SCLogWarning("duplicate instance for %s in '%s'", |
74 | 35.6k | DetectEngineBufferTypeGetNameById(de_ctx, list), s->sig_str); |
75 | 35.6k | s->init_data->curbuf = b; |
76 | 35.6k | return 0; |
77 | 35.6k | } |
78 | 179k | } |
79 | 4.50M | } |
80 | | |
81 | 533k | if (list < DETECT_SM_LIST_MAX) |
82 | 0 | return 0; |
83 | | |
84 | 533k | if (SignatureInitDataBufferCheckExpand(s) < 0) { |
85 | 2 | SCLogError("failed to expand rule buffer array"); |
86 | 2 | return -1; |
87 | 2 | } |
88 | | |
89 | | /* initialize new buffer */ |
90 | 533k | s->init_data->curbuf = &s->init_data->buffers[s->init_data->buffer_index++]; |
91 | 533k | s->init_data->curbuf->id = list; |
92 | 533k | s->init_data->curbuf->head = NULL; |
93 | 533k | s->init_data->curbuf->tail = NULL; |
94 | 533k | s->init_data->curbuf->multi_capable = |
95 | 533k | DetectEngineBufferTypeSupportsMultiInstanceGetById(de_ctx, list); |
96 | 533k | if (s->init_data->init_flags & SIG_FLAG_INIT_FORCE_TOCLIENT) { |
97 | 4.38k | s->init_data->curbuf->only_tc = true; |
98 | 4.38k | } |
99 | 533k | if (s->init_data->init_flags & SIG_FLAG_INIT_FORCE_TOSERVER) { |
100 | 1.92k | s->init_data->curbuf->only_ts = true; |
101 | 1.92k | } |
102 | | |
103 | 533k | SCLogDebug("new: idx %u list %d set up curbuf %p", s->init_data->buffer_index - 1, list, |
104 | 533k | s->init_data->curbuf); |
105 | | |
106 | 533k | return 0; |
107 | 533k | } |
108 | | |
109 | | int DetectBufferGetActiveList(DetectEngineCtx *de_ctx, Signature *s) |
110 | 1.52M | { |
111 | 1.52M | BUG_ON(s->init_data == NULL); |
112 | | |
113 | 1.52M | if (s->init_data->list && s->init_data->transforms.cnt) { |
114 | 114k | if (s->init_data->list == DETECT_SM_LIST_NOTSET || |
115 | 114k | s->init_data->list < DETECT_SM_LIST_DYNAMIC_START) { |
116 | 23 | SCLogError("previous transforms not consumed " |
117 | 23 | "(list: %u, transform_cnt %u)", |
118 | 23 | s->init_data->list, s->init_data->transforms.cnt); |
119 | 23 | SCReturnInt(-1); |
120 | 23 | } |
121 | | |
122 | 114k | SCLogDebug("buffer %d has transform(s) registered: %d", s->init_data->list, |
123 | 114k | s->init_data->transforms.cnt); |
124 | 114k | int new_list = DetectEngineBufferTypeGetByIdTransforms(de_ctx, s->init_data->list, |
125 | 114k | s->init_data->transforms.transforms, s->init_data->transforms.cnt); |
126 | 114k | if (new_list == -1) { |
127 | 0 | SCReturnInt(-1); |
128 | 0 | } |
129 | 114k | int base_list = s->init_data->list; |
130 | 114k | SCLogDebug("new_list %d", new_list); |
131 | 114k | s->init_data->list = new_list; |
132 | 114k | s->init_data->list_set = false; |
133 | | // reset transforms now that we've set up the list |
134 | 114k | s->init_data->transforms.cnt = 0; |
135 | | |
136 | 114k | if (s->init_data->curbuf && s->init_data->curbuf->head != NULL) { |
137 | 16.3k | if (SignatureInitDataBufferCheckExpand(s) < 0) { |
138 | 2 | SCLogError("failed to expand rule buffer array"); |
139 | 2 | return -1; |
140 | 2 | } |
141 | 16.3k | s->init_data->curbuf = &s->init_data->buffers[s->init_data->buffer_index++]; |
142 | 16.3k | s->init_data->curbuf->multi_capable = |
143 | 16.3k | DetectEngineBufferTypeSupportsMultiInstanceGetById(de_ctx, base_list); |
144 | 16.3k | } |
145 | 114k | if (s->init_data->curbuf == NULL) { |
146 | 0 | SCLogError("failed to setup buffer"); |
147 | 0 | DEBUG_VALIDATE_BUG_ON(1); |
148 | 0 | SCReturnInt(-1); |
149 | 0 | } |
150 | 114k | s->init_data->curbuf->id = new_list; |
151 | 114k | SCLogDebug("new list after applying transforms: %u", new_list); |
152 | 114k | } |
153 | | |
154 | 1.52M | SCReturnInt(0); |
155 | 1.52M | } |
156 | | |
157 | | SigMatch *DetectBufferGetFirstSigMatch(const Signature *s, const uint32_t buf_id) |
158 | 0 | { |
159 | 0 | for (uint32_t i = 0; i < s->init_data->buffer_index; i++) { |
160 | 0 | if (buf_id == s->init_data->buffers[i].id) { |
161 | 0 | return s->init_data->buffers[i].head; |
162 | 0 | } |
163 | 0 | } |
164 | 0 | return NULL; |
165 | 0 | } |
166 | | |
167 | | SigMatch *DetectBufferGetLastSigMatch(const Signature *s, const uint32_t buf_id) |
168 | 0 | { |
169 | 0 | SigMatch *last = NULL; |
170 | 0 | for (uint32_t i = 0; i < s->init_data->buffer_index; i++) { |
171 | 0 | if (buf_id == s->init_data->buffers[i].id) { |
172 | 0 | last = s->init_data->buffers[i].tail; |
173 | 0 | } |
174 | 0 | } |
175 | 0 | return last; |
176 | 0 | } |
177 | | |
178 | | int SCDetectSignatureAddTransform(Signature *s, int transform, void *options) |
179 | 187k | { |
180 | | /* we only support buffers */ |
181 | 187k | if (s->init_data->list == 0) { |
182 | 0 | SCReturnInt(-1); |
183 | 0 | } |
184 | 187k | if (!s->init_data->list_set) { |
185 | 2.92k | SCLogError("transforms must directly follow stickybuffers"); |
186 | 2.92k | SCReturnInt(-1); |
187 | 2.92k | } |
188 | 184k | if (s->init_data->transforms.cnt >= DETECT_TRANSFORMS_MAX) { |
189 | 2 | SCReturnInt(-1); |
190 | 2 | } |
191 | | |
192 | 184k | s->init_data->transforms.transforms[s->init_data->transforms.cnt].transform = transform; |
193 | 184k | s->init_data->transforms.transforms[s->init_data->transforms.cnt].options = options; |
194 | | |
195 | 184k | s->init_data->transforms.cnt++; |
196 | 184k | SCLogDebug("Added transform #%d [%s]", s->init_data->transforms.cnt, s->sig_str); |
197 | | |
198 | 184k | SCReturnInt(0); |
199 | 184k | } |