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(InspectionBuffer *buffer, void *options);
42 #ifdef UNITTESTS
44 #endif
45 
47 {
50  "modify buffer via PCRE before inspection";
51  sigmatch_table[DETECT_TRANSFORM_PCREXFORM].url = "/rules/transforms.html#pcre-xform";
53  DetectTransformPcrexform;
55  DetectTransformPcrexformFree;
57  DetectTransformPcrexformSetup;
58 #ifdef UNITTESTS
60 #endif
62 }
63 
64 static void DetectTransformPcrexformFree(DetectEngineCtx *de_ctx, void *ptr)
65 {
66  if (ptr != NULL) {
68  pcre2_match_context_free(pxd->context);
69  pcre2_code_free(pxd->regex);
70  SCFree(pxd);
71  }
72 }
73 
74 /**
75  * \internal
76  * \brief Apply the pcrexform keyword to the last pattern match
77  * \param det_ctx detection engine ctx
78  * \param s signature
79  * \param regexstr options string
80  * \retval 0 ok
81  * \retval -1 failure
82  */
83 static int DetectTransformPcrexformSetup (DetectEngineCtx *de_ctx, Signature *s, const char *regexstr)
84 {
85  SCEnter();
86 
87  // Create pxd from regexstr
88  DetectTransformPcrexformData *pxd = SCCalloc(1, sizeof(*pxd));
89  if (pxd == NULL) {
90  SCLogDebug("pxd allocation failed");
91  SCReturnInt(-1);
92  }
93 
94  pxd->context = pcre2_match_context_create(NULL);
95  if (pxd->context == NULL) {
96  SCFree(pxd);
97  SCReturnInt(-1);
98  }
99  pcre2_set_match_limit(pxd->context, SC_MATCH_LIMIT_DEFAULT);
100  pcre2_set_recursion_limit(pxd->context, SC_MATCH_LIMIT_RECURSION_DEFAULT);
101  int en;
102  PCRE2_SIZE eo;
103  pxd->regex = pcre2_compile((PCRE2_SPTR8)regexstr, PCRE2_ZERO_TERMINATED, 0, &en, &eo, NULL);
104  if (pxd->regex == NULL) {
105  PCRE2_UCHAR buffer[256];
106  pcre2_get_error_message(en, buffer, sizeof(buffer));
107  SCLogError("pcre2 compile of \"%s\" failed at "
108  "offset %d: %s",
109  regexstr, (int)eo, buffer);
110  pcre2_match_context_free(pxd->context);
111  SCFree(pxd);
112  SCReturnInt(-1);
113  }
114  // check pcd->regex has exactly one capture expression
115  uint32_t nb;
116  if (pcre2_pattern_info(pxd->regex, PCRE2_INFO_CAPTURECOUNT, &nb) < 0) {
117  SCLogError("pcrexform failed getting info about capturecount");
118  DetectTransformPcrexformFree(de_ctx, pxd);
119  SCReturnInt(-1);
120  }
121  if (nb != 1) {
122  SCLogError("pcrexform needs exactly one substring capture, found %" PRIu32, nb);
123  DetectTransformPcrexformFree(de_ctx, pxd);
124  SCReturnInt(-1);
125  }
126 
128  if (r != 0) {
129  DetectTransformPcrexformFree(de_ctx, pxd);
130  }
131 
132  SCReturnInt(r);
133 }
134 
135 static void DetectTransformPcrexform(InspectionBuffer *buffer, void *options)
136 {
137  const char *input = (const char *)buffer->inspect;
138  const uint32_t input_len = buffer->inspect_len;
139  DetectTransformPcrexformData *pxd = options;
140 
141  pcre2_match_data *match = pcre2_match_data_create_from_pattern(pxd->regex, NULL);
142  int ret = pcre2_match(pxd->regex, (PCRE2_SPTR8)input, input_len, 0, 0, match, pxd->context);
143 
144  if (ret > 0) {
145  const char *str;
146  PCRE2_SIZE caplen;
147  ret = pcre2_substring_get_bynumber(match, 1, (PCRE2_UCHAR8 **)&str, &caplen);
148 
149  if (ret >= 0) {
150  InspectionBufferCopy(buffer, (uint8_t *)str, (uint32_t)caplen);
151  pcre2_substring_free((PCRE2_UCHAR8 *)str);
152  }
153  }
154  pcre2_match_data_free(match);
155 }
156 
157 #ifdef UNITTESTS
159 #endif
SigTableElmt_::url
const char * url
Definition: detect.h:1312
SC_MATCH_LIMIT_DEFAULT
#define SC_MATCH_LIMIT_DEFAULT
Definition: detect-pcre.h:39
detect-engine.h
SigTableElmt_::desc
const char * desc
Definition: detect.h:1311
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:128
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1299
SigTableElmt_::name
const char * name
Definition: detect.h:1309
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
InspectionBuffer
Definition: detect.h:373
SigTableElmt_::flags
uint16_t flags
Definition: detect.h:1303
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:843
DetectTransformPcrexformData
struct DetectTransformPcrexformData DetectTransformPcrexformData
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1294
detect-pcre.h
SIGMATCH_QUOTES_MANDATORY
#define SIGMATCH_QUOTES_MANDATORY
Definition: detect.h:1509
detect-transform-pcrexform.h
DetectTransformPcrexformData::regex
pcre2_code * regex
Definition: detect-transform-pcrexform.c:35
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
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:40
DetectTransformPcrexformData
Definition: detect-transform-pcrexform.c:34
DetectTransformPcrexformRegister
void DetectTransformPcrexformRegister(void)
Definition: detect-transform-pcrexform.c:46
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:1656
detect-transform-pcrexform.c
suricata-common.h
SigTableElmt_::Transform
void(* Transform)(InspectionBuffer *, void *context)
Definition: detect.h:1290
InspectionBuffer::inspect_len
uint32_t inspect_len
Definition: detect.h:376
InspectionBuffer::inspect
const uint8_t * inspect
Definition: detect.h:374
str
#define str(s)
Definition: suricata-common.h:291
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:603
DetectSignatureAddTransform
int DetectSignatureAddTransform(Signature *s, int transform, void *options)
Definition: detect-parse.c:1713
DetectTransformPcrexformData::context
pcre2_match_context * context
Definition: detect-transform-pcrexform.c:36
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:1301