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"
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
41static int DetectTransformPcrexformSetup (DetectEngineCtx *, Signature *, const char *);
42static void DetectTransformPcrexformFree(DetectEngineCtx *, void *);
43static void DetectTransformPcrexform(
44 DetectEngineThreadCtx *det_ctx, InspectionBuffer *buffer, void *options);
45#ifdef UNITTESTS
47#endif
48
49static 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
77static 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 */
99static 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
159static 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
int SCDetectSignatureAddTransform(Signature *s, int transform, void *options)
void InspectionBufferCopy(InspectionBuffer *buffer, uint8_t *buf, uint32_t buf_len)
@ DETECT_TRANSFORM_PCREXFORM
SigTableElmt * sigmatch_table
#define SC_MATCH_LIMIT_RECURSION_DEFAULT
Definition detect-pcre.h:44
#define SC_MATCH_LIMIT_DEFAULT
Definition detect-pcre.h:43
void DetectTransformPcrexformRegister(void)
void DetectTransformPcrexformRegisterTests(void)
this function registers unit tests for DetectTransformPcrexform
#define SIGMATCH_QUOTES_MANDATORY
Definition detect.h:1668
DetectEngineCtx * de_ctx
main detection engine ctx
Definition detect.h:932
const char * url
Definition detect.h:1462
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition detect.h:1441
void(* Free)(DetectEngineCtx *, void *)
Definition detect.h:1446
uint16_t flags
Definition detect.h:1450
const char * desc
Definition detect.h:1461
void(* RegisterTests)(void)
Definition detect.h:1448
void(* TransformId)(const uint8_t **data, uint32_t *length, void *context)
Definition detect.h:1438
const char * name
Definition detect.h:1459
void(* Transform)(DetectEngineThreadCtx *, InspectionBuffer *, void *context)
Definition detect.h:1434
Signature container.
Definition detect.h:668
#define str(s)
#define SCEnter(...)
Definition util-debug.h:277
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCReturnInt(x)
Definition util-debug.h:281
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
#define SCFree(p)
Definition util-mem.h:61
#define SCCalloc(nm, sz)
Definition util-mem.h:53
#define SCStrdup(s)
Definition util-mem.h:56