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  uint8_t output[input_len]; // we can only shrink
111  uint8_t *oi = output, *os = output;
112 
113  //PrintRawDataFp(stdout, input, input_len);
114  for (uint32_t i = 0; i < input_len; ) {
115  if (!(isspace(*input))) {
116  *oi++ = *input++;
117  i++;
118  } else {
119  *oi++ = *input++;
120  i++;
121 
122  while (i < input_len && isspace(*input)) {
123  input++;
124  i++;
125  }
126  }
127  }
128  uint32_t output_size = oi - os;
129  //PrintRawDataFp(stdout, output, output_size);
130 
131  InspectionBufferCopy(buffer, os, output_size);
132 }
133 
134 #ifdef UNITTESTS
135 static int TransformDoubleWhitespace(InspectionBuffer *buffer)
136 {
137  const uint8_t *input = buffer->inspect;
138  const uint32_t input_len = buffer->inspect_len;
139  uint8_t output[input_len * 2]; // if all chars are whitespace this fits
140  uint8_t *oi = output, *os = output;
141 
142  PrintRawDataFp(stdout, input, input_len);
143  for (uint32_t i = 0; i < input_len; i++) {
144  if (isspace(*input)) {
145  *oi++ = *input;
146  }
147  *oi++ = *input;
148  input++;
149  }
150  uint32_t output_size = oi - os;
151  PrintRawDataFp(stdout, output, output_size);
152 
153  InspectionBufferCopy(buffer, os, output_size);
154  return 0;
155 }
156 
157 static int DetectTransformCompressWhitespaceTest01(void)
158 {
159  const uint8_t *input = (const uint8_t *)" A B C D ";
160  uint32_t input_len = strlen((char *)input);
161 
162  InspectionBuffer buffer;
163  InspectionBufferInit(&buffer, 9);
164  InspectionBufferSetup(&buffer, input, input_len);
165  PrintRawDataFp(stdout, buffer.inspect, buffer.inspect_len);
166  TransformCompressWhitespace(&buffer, NULL);
167  PrintRawDataFp(stdout, buffer.inspect, buffer.inspect_len);
168  InspectionBufferFree(&buffer);
169  PASS;
170 }
171 
172 static int DetectTransformCompressWhitespaceTest02(void)
173 {
174  const uint8_t *input = (const uint8_t *)" A B C D ";
175  uint32_t input_len = strlen((char *)input);
176 
177  InspectionBuffer buffer;
178  InspectionBufferInit(&buffer, 9);
179  InspectionBufferSetup(&buffer, input, input_len);
180  PrintRawDataFp(stdout, buffer.inspect, buffer.inspect_len);
181  TransformDoubleWhitespace(&buffer);
182  PrintRawDataFp(stdout, buffer.inspect, buffer.inspect_len);
183  TransformDoubleWhitespace(&buffer);
184  PrintRawDataFp(stdout, buffer.inspect, buffer.inspect_len);
185  TransformCompressWhitespace(&buffer, NULL);
186  PrintRawDataFp(stdout, buffer.inspect, buffer.inspect_len);
187  InspectionBufferFree(&buffer);
188  PASS;
189 }
190 
191 static int DetectTransformCompressWhitespaceTest03(void)
192 {
193  const uint8_t *input = (const uint8_t *)" A B C D ";
194  uint32_t input_len = strlen((char *)input);
195 
196  InspectionBuffer buffer;
197  InspectionBufferInit(&buffer, 10);
198  InspectionBufferSetup(&buffer, input, input_len);
199  PrintRawDataFp(stdout, buffer.inspect, buffer.inspect_len);
200  FAIL_IF(TransformCompressWhitespaceValidate(buffer.inspect, buffer.inspect_len, NULL));
201  PASS;
202 }
203 
204 static int DetectTransformCompressWhitespaceTest04(void)
205 {
206  const uint8_t *input = (const uint8_t *)" A B C D ";
207  uint32_t input_len = strlen((char *)input);
208 
209  InspectionBuffer buffer;
210  InspectionBufferInit(&buffer, 9);
211  InspectionBufferSetup(&buffer, input, input_len);
212  TransformDoubleWhitespace(&buffer);
213  PrintRawDataFp(stdout, buffer.inspect, buffer.inspect_len);
214  FAIL_IF(TransformCompressWhitespaceValidate(buffer.inspect, buffer.inspect_len, NULL));
215  PASS;
216 }
217 
218 static void DetectTransformCompressWhitespaceRegisterTests(void)
219 {
220  UtRegisterTest("DetectTransformCompressWhitespaceTest01",
221  DetectTransformCompressWhitespaceTest01);
222  UtRegisterTest("DetectTransformCompressWhitespaceTest02",
223  DetectTransformCompressWhitespaceTest02);
225  "DetectTransformCompressWhitespaceTest03", DetectTransformCompressWhitespaceTest03);
227  "DetectTransformCompressWhitespaceTest04", DetectTransformCompressWhitespaceTest04);
228 }
229 #endif
SigTableElmt_::url
const char * url
Definition: detect.h:1214
detect-engine.h
SigTableElmt_::desc
const char * desc
Definition: detect.h:1213
SigTableElmt_::name
const char * name
Definition: detect.h:1211
DETECT_TRANSFORM_COMPRESS_WHITESPACE
@ DETECT_TRANSFORM_COMPRESS_WHITESPACE
Definition: detect-engine-register.h:292
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
InspectionBuffer
Definition: detect.h:344
SigTableElmt_::flags
uint16_t flags
Definition: detect.h:1205
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:767
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1196
detect-engine-prefilter.h
util-unittest.h
InspectionBufferInit
void InspectionBufferInit(InspectionBuffer *buffer, uint32_t initial_size)
Definition: detect-engine.c:1110
SigTableElmt_::TransformValidate
bool(* TransformValidate)(const uint8_t *content, uint16_t content_len, void *context)
Definition: detect.h:1193
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:300
detect.h
PrintRawDataFp
void PrintRawDataFp(FILE *fp, const uint8_t *buf, uint32_t buflen)
Definition: util-print.c:141
InspectionBufferCopy
void InspectionBufferCopy(InspectionBuffer *buffer, uint8_t *buf, uint32_t buf_len)
Definition: detect-engine.c:1156
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
suricata-common.h
InspectionBufferSetup
void InspectionBufferSetup(InspectionBuffer *buffer, const uint8_t *data, const uint32_t data_len)
setup the buffer with our initial data
Definition: detect-engine.c:1120
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:73
SigTableElmt_::Transform
void(* Transform)(InspectionBuffer *, void *context)
Definition: detect.h:1192
InspectionBuffer::inspect_len
uint32_t inspect_len
Definition: detect.h:347
InspectionBuffer::inspect
const uint8_t * inspect
Definition: detect.h:345
detect-parse.h
Signature_
Signature container.
Definition: detect.h:528
DetectSignatureAddTransform
int DetectSignatureAddTransform(Signature *s, int transform, void *options)
Definition: detect-parse.c:1455
SIGMATCH_NOOPT
#define SIGMATCH_NOOPT
Definition: detect.h:1380
DetectTransformCompressWhitespaceRegister
void DetectTransformCompressWhitespaceRegister(void)
Definition: detect-transform-compress-whitespace.c:45
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:304
InspectionBufferFree
void InspectionBufferFree(InspectionBuffer *buffer)
Definition: detect-engine.c:1127
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1203