suricata
detect-transform-pcrexform.c
Go to the documentation of this file.
1 /* Copyright (C) 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 Jeff Lucovsky <jeff@lucovsky.org>
22  *
23  * Implements the pcrexform transform keyword with option support
24  */
25 
26 #include "suricata-common.h"
27 
28 #include "detect.h"
29 #include "detect-engine.h"
30 #include "detect-engine-buffer.h"
32 #include "detect-pcre.h"
33 
35  pcre2_code *regex;
36  pcre2_match_context *context;
37  uint8_t *id_data;
38  uint32_t id_data_len;
40 
41 static int DetectTransformPcrexformSetup (DetectEngineCtx *, Signature *, const char *);
42 static void DetectTransformPcrexformFree(DetectEngineCtx *, void *);
43 static void DetectTransformPcrexform(
44  DetectEngineThreadCtx *det_ctx, InspectionBuffer *buffer, void *options);
45 #ifdef UNITTESTS
47 #endif
48 
49 static void DetectTransformPcrexformId(const uint8_t **data, uint32_t *length, void *context)
50 {
51  if (context) {
53  *data = (const uint8_t *)pxd->id_data;
54  *length = pxd->id_data_len;
55  }
56 }
57 
59 {
62  "modify buffer via PCRE before inspection";
63  sigmatch_table[DETECT_TRANSFORM_PCREXFORM].url = "/rules/transforms.html#pcre-xform";
65  DetectTransformPcrexform;
66  sigmatch_table[DETECT_TRANSFORM_PCREXFORM].TransformId = DetectTransformPcrexformId;
68  DetectTransformPcrexformFree;
70  DetectTransformPcrexformSetup;
71 #ifdef UNITTESTS
73 #endif
75 }
76 
77 static void DetectTransformPcrexformFree(DetectEngineCtx *de_ctx, void *ptr)
78 {
79  if (ptr != NULL) {
81 
82  pcre2_match_context_free(pxd->context);
83  pcre2_code_free(pxd->regex);
84 
85  SCFree(pxd->id_data);
86  SCFree(pxd);
87  }
88 }
89 
90 /**
91  * \internal
92  * \brief Apply the pcrexform keyword to the last pattern match
93  * \param det_ctx detection engine ctx
94  * \param s signature
95  * \param regexstr options string
96  * \retval 0 ok
97  * \retval -1 failure
98  */
99 static int DetectTransformPcrexformSetup (DetectEngineCtx *de_ctx, Signature *s, const char *regexstr)
100 {
101  SCEnter();
102 
103  // Create pxd from regexstr
104  DetectTransformPcrexformData *pxd = SCCalloc(1, sizeof(*pxd));
105  if (pxd == NULL) {
106  SCLogDebug("pxd allocation failed");
107  SCReturnInt(-1);
108  }
109 
110  pxd->context = pcre2_match_context_create(NULL);
111  if (pxd->context == NULL) {
112  SCFree(pxd);
113  SCReturnInt(-1);
114  }
115  pcre2_set_match_limit(pxd->context, SC_MATCH_LIMIT_DEFAULT);
116  pcre2_set_recursion_limit(pxd->context, SC_MATCH_LIMIT_RECURSION_DEFAULT);
117  int en;
118  PCRE2_SIZE eo;
119  pxd->regex = pcre2_compile((PCRE2_SPTR8)regexstr, PCRE2_ZERO_TERMINATED, 0, &en, &eo, NULL);
120  if (pxd->regex == NULL) {
121  PCRE2_UCHAR buffer[256];
122  pcre2_get_error_message(en, buffer, sizeof(buffer));
123  SCLogError("pcre2 compile of \"%s\" failed at "
124  "offset %d: %s",
125  regexstr, (int)eo, buffer);
126  pcre2_match_context_free(pxd->context);
127  SCFree(pxd);
128  SCReturnInt(-1);
129  }
130 
131  // check pcd->regex has exactly one capture expression
132  uint32_t nb;
133  if (pcre2_pattern_info(pxd->regex, PCRE2_INFO_CAPTURECOUNT, &nb) < 0) {
134  SCLogError("pcrexform failed getting info about capturecount");
135  DetectTransformPcrexformFree(de_ctx, pxd);
136  SCReturnInt(-1);
137  }
138  if (nb != 1) {
139  SCLogError("pcrexform needs exactly one substring capture, found %" PRIu32, nb);
140  DetectTransformPcrexformFree(de_ctx, pxd);
141  SCReturnInt(-1);
142  }
143 
144  pxd->id_data = (uint8_t *)SCStrdup(regexstr);
145  if (pxd->id_data == NULL) {
146  DetectTransformPcrexformFree(de_ctx, pxd);
147  SCReturnInt(-1);
148  }
149  pxd->id_data_len = (uint32_t)strlen(regexstr);
150 
152  if (r != 0) {
153  DetectTransformPcrexformFree(de_ctx, pxd);
154  }
155 
156  SCReturnInt(r);
157 }
158 
159 static void DetectTransformPcrexform(
160  DetectEngineThreadCtx *det_ctx, InspectionBuffer *buffer, void *options)
161 {
162  const char *input = (const char *)buffer->inspect;
163  const uint32_t input_len = buffer->inspect_len;
164  DetectTransformPcrexformData *pxd = options;
165 
166  pcre2_match_data *match = pcre2_match_data_create_from_pattern(pxd->regex, NULL);
167  int ret = pcre2_match(pxd->regex, (PCRE2_SPTR8)input, input_len, 0, 0, match, pxd->context);
168 
169  if (ret > 0) {
170  const char *str;
171  PCRE2_SIZE caplen;
172  ret = pcre2_substring_get_bynumber(match, 1, (PCRE2_UCHAR8 **)&str, &caplen);
173 
174  if (ret >= 0) {
175  InspectionBufferCopy(buffer, (uint8_t *)str, (uint32_t)caplen);
176  pcre2_substring_free((PCRE2_UCHAR8 *)str);
177  }
178  }
179  pcre2_match_data_free(match);
180 }
181 
182 #ifdef UNITTESTS
184 #endif
SigTableElmt_::url
const char * url
Definition: detect.h:1422
SC_MATCH_LIMIT_DEFAULT
#define SC_MATCH_LIMIT_DEFAULT
Definition: detect-pcre.h:43
detect-engine.h
SigTableElmt_::desc
const char * desc
Definition: detect.h:1421
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:79
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1409
SigTableElmt_::name
const char * name
Definition: detect.h:1419
InspectionBufferCopy
void InspectionBufferCopy(InspectionBuffer *buffer, uint8_t *buf, uint32_t buf_len)
Definition: detect-engine-inspect-buffer.c:246
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:270
DetectTransformPcrexformData::id_data
uint8_t * id_data
Definition: detect-transform-pcrexform.c:37
InspectionBuffer
Definition: detect-engine-inspect-buffer.h:34
SigTableElmt_::flags
uint16_t flags
Definition: detect.h:1413
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:919
DetectTransformPcrexformData
struct DetectTransformPcrexformData DetectTransformPcrexformData
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1404
detect-pcre.h
SIGMATCH_QUOTES_MANDATORY
#define SIGMATCH_QUOTES_MANDATORY
Definition: detect.h:1628
detect-transform-pcrexform.h
DetectTransformPcrexformData::regex
pcre2_code * regex
Definition: detect-transform-pcrexform.c:35
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:18
DetectEngineThreadCtx_
Definition: detect.h:1211
DETECT_TRANSFORM_PCREXFORM
@ DETECT_TRANSFORM_PCREXFORM
Definition: detect-engine-register.h:311
SCEnter
#define SCEnter(...)
Definition: util-debug.h:272
detect.h
SC_MATCH_LIMIT_RECURSION_DEFAULT
#define SC_MATCH_LIMIT_RECURSION_DEFAULT
Definition: detect-pcre.h:44
DetectTransformPcrexformData::id_data_len
uint32_t id_data_len
Definition: detect-transform-pcrexform.c:38
DetectTransformPcrexformData
Definition: detect-transform-pcrexform.c:34
DetectTransformPcrexformRegister
void DetectTransformPcrexformRegister(void)
Definition: detect-transform-pcrexform.c:58
DetectTransformPcrexformRegisterTests
void DetectTransformPcrexformRegisterTests(void)
this function registers unit tests for DetectTransformPcrexform
Definition: detect-transform-pcrexform.c:81
detect-transform-pcrexform.c
suricata-common.h
detect-engine-buffer.h
SCStrdup
#define SCStrdup(s)
Definition: util-mem.h:56
InspectionBuffer::inspect_len
uint32_t inspect_len
Definition: detect-engine-inspect-buffer.h:37
InspectionBuffer::inspect
const uint8_t * inspect
Definition: detect-engine-inspect-buffer.h:35
str
#define str(s)
Definition: suricata-common.h:308
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:262
SCFree
#define SCFree(p)
Definition: util-mem.h:61
Signature_
Signature container.
Definition: detect.h:657
SCDetectSignatureAddTransform
int SCDetectSignatureAddTransform(Signature *s, int transform, void *options)
Definition: detect-engine-buffer.c:178
DetectTransformPcrexformData::context
pcre2_match_context * context
Definition: detect-transform-pcrexform.c:36
SigTableElmt_::Transform
void(* Transform)(DetectEngineThreadCtx *, InspectionBuffer *, void *context)
Definition: detect.h:1397
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:276
SigTableElmt_::TransformId
void(* TransformId)(const uint8_t **data, uint32_t *length, void *context)
Definition: detect.h:1401
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1411