suricata
detect-transform-compress-whitespace.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2020 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  * Implements the compress_whitespace transform keyword
24  */
25 
26 #include "suricata-common.h"
27 
28 #include "detect.h"
29 #include "detect-engine.h"
31 #include "detect-parse.h"
33 
34 #include "util-unittest.h"
35 #include "util-print.h"
36 
37 static int DetectTransformCompressWhitespaceSetup (DetectEngineCtx *, Signature *, const char *);
38 #ifdef UNITTESTS
39 static void DetectTransformCompressWhitespaceRegisterTests(void);
40 #endif
41 static void TransformCompressWhitespace(InspectionBuffer *buffer, void *options);
42 static bool TransformCompressWhitespaceValidate(
43  const uint8_t *content, uint16_t content_len, void *options);
44 
46 {
49  "modify buffer to compress consecutive whitespace characters "
50  "into a single one before inspection";
52  "/rules/transforms.html#compress-whitespace";
54  TransformCompressWhitespace;
56  TransformCompressWhitespaceValidate;
58  DetectTransformCompressWhitespaceSetup;
59 #ifdef UNITTESTS
61  DetectTransformCompressWhitespaceRegisterTests;
62 #endif
64 }
65 
66 /**
67  * \internal
68  * \brief Apply the compress_whitespace keyword to the last pattern match
69  * \param det_ctx detection engine ctx
70  * \param s signature
71  * \param nullstr should be null
72  * \retval 0 ok
73  * \retval -1 failure
74  */
75 static int DetectTransformCompressWhitespaceSetup (DetectEngineCtx *de_ctx, Signature *s, const char *nullstr)
76 {
77  SCEnter();
79  SCReturnInt(r);
80 }
81 
82 /*
83  * \brief Validate content bytes to see if it's compatible with this transform
84  * \param content Byte array to check for compatibility
85  * \param content_len Number of bytes to check
86  * \param options Ignored
87  * \retval false If the string contains spaces
88  * \retval true Otherwise.
89  */
90 static bool TransformCompressWhitespaceValidate(
91  const uint8_t *content, uint16_t content_len, void *options)
92 {
93  if (content) {
94  for (uint32_t i = 0; i < content_len; i++) {
95  if (!isspace(*content++)) {
96  continue;
97  }
98  if ((i + 1) < content_len && isspace(*content)) {
99  return false;
100  }
101  }
102  }
103  return true;
104 }
105 
106 static void TransformCompressWhitespace(InspectionBuffer *buffer, void *options)
107 {
108  const uint8_t *input = buffer->inspect;
109  const uint32_t input_len = buffer->inspect_len;
110  if (input_len == 0) {
111  return;
112  }
113 
114  uint8_t output[input_len]; // we can only shrink
115  uint8_t *oi = output, *os = output;
116 
117  //PrintRawDataFp(stdout, input, input_len);
118  for (uint32_t i = 0; i < input_len; ) {
119  if (!(isspace(*input))) {
120  *oi++ = *input++;
121  i++;
122  } else {
123  *oi++ = *input++;
124  i++;
125 
126  while (i < input_len && isspace(*input)) {
127  input++;
128  i++;
129  }
130  }
131  }
132  uint32_t output_size = oi - os;
133  //PrintRawDataFp(stdout, output, output_size);
134 
135  InspectionBufferCopy(buffer, os, output_size);
136 }
137 
138 #ifdef UNITTESTS
139 static int TransformDoubleWhitespace(InspectionBuffer *buffer)
140 {
141  const uint8_t *input = buffer->inspect;
142  const uint32_t input_len = buffer->inspect_len;
143  uint8_t output[input_len * 2]; // if all chars are whitespace this fits
144  uint8_t *oi = output, *os = output;
145 
146  PrintRawDataFp(stdout, input, input_len);
147  for (uint32_t i = 0; i < input_len; i++) {
148  if (isspace(*input)) {
149  *oi++ = *input;
150  }
151  *oi++ = *input;
152  input++;
153  }
154  uint32_t output_size = oi - os;
155  PrintRawDataFp(stdout, output, output_size);
156 
157  InspectionBufferCopy(buffer, os, output_size);
158  return 0;
159 }
160 
161 static int DetectTransformCompressWhitespaceTest01(void)
162 {
163  const uint8_t *input = (const uint8_t *)" A B C D ";
164  uint32_t input_len = strlen((char *)input);
165 
166  InspectionBuffer buffer;
167  InspectionBufferInit(&buffer, 9);
168  InspectionBufferSetup(NULL, -1, &buffer, input, input_len);
169  PrintRawDataFp(stdout, buffer.inspect, buffer.inspect_len);
170  TransformCompressWhitespace(&buffer, NULL);
171  PrintRawDataFp(stdout, buffer.inspect, buffer.inspect_len);
172  InspectionBufferFree(&buffer);
173  PASS;
174 }
175 
176 static int DetectTransformCompressWhitespaceTest02(void)
177 {
178  const uint8_t *input = (const uint8_t *)" A B C D ";
179  uint32_t input_len = strlen((char *)input);
180 
181  InspectionBuffer buffer;
182  InspectionBufferInit(&buffer, 9);
183  InspectionBufferSetup(NULL, -1, &buffer, input, input_len);
184  PrintRawDataFp(stdout, buffer.inspect, buffer.inspect_len);
185  TransformDoubleWhitespace(&buffer);
186  PrintRawDataFp(stdout, buffer.inspect, buffer.inspect_len);
187  TransformDoubleWhitespace(&buffer);
188  PrintRawDataFp(stdout, buffer.inspect, buffer.inspect_len);
189  TransformCompressWhitespace(&buffer, NULL);
190  PrintRawDataFp(stdout, buffer.inspect, buffer.inspect_len);
191  InspectionBufferFree(&buffer);
192  PASS;
193 }
194 
195 static int DetectTransformCompressWhitespaceTest03(void)
196 {
197  const uint8_t *input = (const uint8_t *)" A B C D ";
198  uint32_t input_len = strlen((char *)input);
199 
200  InspectionBuffer buffer;
201  InspectionBufferInit(&buffer, 10);
202  InspectionBufferSetup(NULL, -1, &buffer, input, input_len);
203  PrintRawDataFp(stdout, buffer.inspect, buffer.inspect_len);
204  FAIL_IF(TransformCompressWhitespaceValidate(buffer.inspect, buffer.inspect_len, NULL));
205  PASS;
206 }
207 
208 static int DetectTransformCompressWhitespaceTest04(void)
209 {
210  const uint8_t *input = (const uint8_t *)" A B C D ";
211  uint32_t input_len = strlen((char *)input);
212 
213  InspectionBuffer buffer;
214  InspectionBufferInit(&buffer, 9);
215  InspectionBufferSetup(NULL, -1, &buffer, input, input_len);
216  TransformDoubleWhitespace(&buffer);
217  PrintRawDataFp(stdout, buffer.inspect, buffer.inspect_len);
218  FAIL_IF(TransformCompressWhitespaceValidate(buffer.inspect, buffer.inspect_len, NULL));
219  PASS;
220 }
221 
222 static void DetectTransformCompressWhitespaceRegisterTests(void)
223 {
224  UtRegisterTest("DetectTransformCompressWhitespaceTest01",
225  DetectTransformCompressWhitespaceTest01);
226  UtRegisterTest("DetectTransformCompressWhitespaceTest02",
227  DetectTransformCompressWhitespaceTest02);
229  "DetectTransformCompressWhitespaceTest03", DetectTransformCompressWhitespaceTest03);
231  "DetectTransformCompressWhitespaceTest04", DetectTransformCompressWhitespaceTest04);
232 }
233 #endif
SigTableElmt_::url
const char * url
Definition: detect.h:1299
detect-engine.h
SigTableElmt_::desc
const char * desc
Definition: detect.h:1298
SigTableElmt_::name
const char * name
Definition: detect.h:1296
DETECT_TRANSFORM_COMPRESS_WHITESPACE
@ DETECT_TRANSFORM_COMPRESS_WHITESPACE
Definition: detect-engine-register.h:331
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
InspectionBuffer
Definition: detect.h:374
SigTableElmt_::flags
uint16_t flags
Definition: detect.h:1290
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:839
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1281
detect-engine-prefilter.h
util-unittest.h
InspectionBufferInit
void InspectionBufferInit(InspectionBuffer *buffer, uint32_t initial_size)
Definition: detect-engine.c:1536
SigTableElmt_::TransformValidate
bool(* TransformValidate)(const uint8_t *content, uint16_t content_len, void *context)
Definition: detect.h:1278
detect-transform-compress-whitespace.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
detect.h
PrintRawDataFp
void PrintRawDataFp(FILE *fp, const uint8_t *buf, uint32_t buflen)
Definition: util-print.c:114
InspectionBufferCopy
void InspectionBufferCopy(InspectionBuffer *buffer, uint8_t *buf, uint32_t buf_len)
Definition: detect-engine.c:1622
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
suricata-common.h
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:127
SigTableElmt_::Transform
void(* Transform)(InspectionBuffer *, void *context)
Definition: detect.h:1277
InspectionBuffer::inspect_len
uint32_t inspect_len
Definition: detect.h:377
InspectionBuffer::inspect
const uint8_t * inspect
Definition: detect.h:375
InspectionBufferSetup
void InspectionBufferSetup(DetectEngineThreadCtx *det_ctx, const int list_id, InspectionBuffer *buffer, const uint8_t *data, const uint32_t data_len)
setup the buffer with our initial data
Definition: detect-engine.c:1574
detect-parse.h
Signature_
Signature container.
Definition: detect.h:596
DetectSignatureAddTransform
int DetectSignatureAddTransform(Signature *s, int transform, void *options)
Definition: detect-parse.c:1728
SIGMATCH_NOOPT
#define SIGMATCH_NOOPT
Definition: detect.h:1476
DetectTransformCompressWhitespaceRegister
void DetectTransformCompressWhitespaceRegister(void)
Definition: detect-transform-compress-whitespace.c:45
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:275
InspectionBufferFree
void InspectionBufferFree(InspectionBuffer *buffer)
Definition: detect-engine.c:1593
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1288