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-parse.h"
32 #include "detect-pcre.h"
33 
35  pcre2_code *regex;
36  pcre2_match_context *context;
38 
39 static int DetectTransformPcrexformSetup (DetectEngineCtx *, Signature *, const char *);
40 static void DetectTransformPcrexformFree(DetectEngineCtx *, void *);
41 static void DetectTransformPcrexform(
42  DetectEngineThreadCtx *det_ctx, InspectionBuffer *buffer, void *options);
43 #ifdef UNITTESTS
45 #endif
46 
48 {
51  "modify buffer via PCRE before inspection";
52  sigmatch_table[DETECT_TRANSFORM_PCREXFORM].url = "/rules/transforms.html#pcre-xform";
54  DetectTransformPcrexform;
56  DetectTransformPcrexformFree;
58  DetectTransformPcrexformSetup;
59 #ifdef UNITTESTS
61 #endif
63 }
64 
65 static void DetectTransformPcrexformFree(DetectEngineCtx *de_ctx, void *ptr)
66 {
67  if (ptr != NULL) {
69  pcre2_match_context_free(pxd->context);
70  pcre2_code_free(pxd->regex);
71  SCFree(pxd);
72  }
73 }
74 
75 /**
76  * \internal
77  * \brief Apply the pcrexform keyword to the last pattern match
78  * \param det_ctx detection engine ctx
79  * \param s signature
80  * \param regexstr options string
81  * \retval 0 ok
82  * \retval -1 failure
83  */
84 static int DetectTransformPcrexformSetup (DetectEngineCtx *de_ctx, Signature *s, const char *regexstr)
85 {
86  SCEnter();
87 
88  // Create pxd from regexstr
89  DetectTransformPcrexformData *pxd = SCCalloc(1, sizeof(*pxd));
90  if (pxd == NULL) {
91  SCLogDebug("pxd allocation failed");
92  SCReturnInt(-1);
93  }
94 
95  pxd->context = pcre2_match_context_create(NULL);
96  if (pxd->context == NULL) {
97  SCFree(pxd);
98  SCReturnInt(-1);
99  }
100  pcre2_set_match_limit(pxd->context, SC_MATCH_LIMIT_DEFAULT);
101  pcre2_set_recursion_limit(pxd->context, SC_MATCH_LIMIT_RECURSION_DEFAULT);
102  int en;
103  PCRE2_SIZE eo;
104  pxd->regex = pcre2_compile((PCRE2_SPTR8)regexstr, PCRE2_ZERO_TERMINATED, 0, &en, &eo, NULL);
105  if (pxd->regex == NULL) {
106  PCRE2_UCHAR buffer[256];
107  pcre2_get_error_message(en, buffer, sizeof(buffer));
108  SCLogError("pcre2 compile of \"%s\" failed at "
109  "offset %d: %s",
110  regexstr, (int)eo, buffer);
111  pcre2_match_context_free(pxd->context);
112  SCFree(pxd);
113  SCReturnInt(-1);
114  }
115  // check pcd->regex has exactly one capture expression
116  uint32_t nb;
117  if (pcre2_pattern_info(pxd->regex, PCRE2_INFO_CAPTURECOUNT, &nb) < 0) {
118  SCLogError("pcrexform failed getting info about capturecount");
119  DetectTransformPcrexformFree(de_ctx, pxd);
120  SCReturnInt(-1);
121  }
122  if (nb != 1) {
123  SCLogError("pcrexform needs exactly one substring capture, found %" PRIu32, nb);
124  DetectTransformPcrexformFree(de_ctx, pxd);
125  SCReturnInt(-1);
126  }
127 
129  if (r != 0) {
130  DetectTransformPcrexformFree(de_ctx, pxd);
131  }
132 
133  SCReturnInt(r);
134 }
135 
136 static void DetectTransformPcrexform(
137  DetectEngineThreadCtx *det_ctx, InspectionBuffer *buffer, void *options)
138 {
139  const char *input = (const char *)buffer->inspect;
140  const uint32_t input_len = buffer->inspect_len;
141  DetectTransformPcrexformData *pxd = options;
142 
143  pcre2_match_data *match = pcre2_match_data_create_from_pattern(pxd->regex, NULL);
144  int ret = pcre2_match(pxd->regex, (PCRE2_SPTR8)input, input_len, 0, 0, match, pxd->context);
145 
146  if (ret > 0) {
147  const char *str;
148  PCRE2_SIZE caplen;
149  ret = pcre2_substring_get_bynumber(match, 1, (PCRE2_UCHAR8 **)&str, &caplen);
150 
151  if (ret >= 0) {
152  InspectionBufferCopy(buffer, (uint8_t *)str, (uint32_t)caplen);
153  pcre2_substring_free((PCRE2_UCHAR8 *)str);
154  }
155  }
156  pcre2_match_data_free(match);
157 }
158 
159 #ifdef UNITTESTS
161 #endif
SigTableElmt_::url
const char * url
Definition: detect.h:1405
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:1404
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:155
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1392
SigTableElmt_::name
const char * name
Definition: detect.h:1402
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
InspectionBuffer
Definition: detect.h:380
SigTableElmt_::flags
uint16_t flags
Definition: detect.h:1396
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:920
DetectTransformPcrexformData
struct DetectTransformPcrexformData DetectTransformPcrexformData
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1387
detect-pcre.h
SIGMATCH_QUOTES_MANDATORY
#define SIGMATCH_QUOTES_MANDATORY
Definition: detect.h:1608
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:1197
DETECT_TRANSFORM_PCREXFORM
@ DETECT_TRANSFORM_PCREXFORM
Definition: detect-engine-register.h:314
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
detect.h
SC_MATCH_LIMIT_RECURSION_DEFAULT
#define SC_MATCH_LIMIT_RECURSION_DEFAULT
Definition: detect-pcre.h:44
DetectTransformPcrexformData
Definition: detect-transform-pcrexform.c:34
DetectTransformPcrexformRegister
void DetectTransformPcrexformRegister(void)
Definition: detect-transform-pcrexform.c:47
DetectTransformPcrexformRegisterTests
void DetectTransformPcrexformRegisterTests(void)
this function registers unit tests for DetectTransformPcrexform
Definition: detect-transform-pcrexform.c:81
InspectionBufferCopy
void InspectionBufferCopy(InspectionBuffer *buffer, uint8_t *buf, uint32_t buf_len)
Definition: detect-engine.c:1768
detect-transform-pcrexform.c
suricata-common.h
InspectionBuffer::inspect_len
uint32_t inspect_len
Definition: detect.h:383
InspectionBuffer::inspect
const uint8_t * inspect
Definition: detect.h:381
str
#define str(s)
Definition: suricata-common.h:300
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
SCFree
#define SCFree(p)
Definition: util-mem.h:61
detect-parse.h
Signature_
Signature container.
Definition: detect.h:669
DetectSignatureAddTransform
int DetectSignatureAddTransform(Signature *s, int transform, void *options)
Definition: detect-parse.c:2105
DetectTransformPcrexformData::context
pcre2_match_context * context
Definition: detect-transform-pcrexform.c:36
SigTableElmt_::Transform
void(* Transform)(DetectEngineThreadCtx *, InspectionBuffer *, void *context)
Definition: detect.h:1383
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:275
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1394