]> git.ipfire.org Git - people/ms/suricata.git/blame - src/detect-mqtt-type.c
core: Remove unneeded consts
[people/ms/suricata.git] / src / detect-mqtt-type.c
CommitLineData
c3136007
SS
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 Sascha Steinbiss <sascha@steinbiss.name>
22 */
23
24#include "suricata-common.h"
25#include "conf.h"
26#include "detect.h"
27#include "detect-parse.h"
28#include "detect-engine.h"
29#include "detect-engine-content-inspection.h"
30#include "detect-mqtt-type.h"
31#include "util-unittest.h"
32
f77fd0c0 33#include "rust.h"
c3136007
SS
34
35static int mqtt_type_id = 0;
36
37static int DetectMQTTTypeMatch(DetectEngineThreadCtx *det_ctx,
38 Flow *f, uint8_t flags, void *state,
39 void *txv, const Signature *s,
40 const SigMatchCtx *ctx);
41static int DetectMQTTTypeSetup (DetectEngineCtx *, Signature *, const char *);
42void MQTTTypeRegisterTests(void);
43void DetectMQTTTypeFree(DetectEngineCtx *de_ctx, void *);
44
2320d628
VJ
45static int DetectEngineInspectMQTTTypeGeneric(DetectEngineCtx *de_ctx,
46 DetectEngineThreadCtx *det_ctx, const struct DetectEngineAppInspectionEngine_ *engine,
47 const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id);
c3136007
SS
48
49/**
50 * \brief Registration function for ipopts: keyword
51 */
52void DetectMQTTTypeRegister (void)
53{
54 sigmatch_table[DETECT_AL_MQTT_TYPE].name = "mqtt.type";
55 sigmatch_table[DETECT_AL_MQTT_TYPE].desc = "match MQTT control packet type";
56 sigmatch_table[DETECT_AL_MQTT_TYPE].url = "/rules/mqtt-keywords.html#mqtt-type";
57 sigmatch_table[DETECT_AL_MQTT_TYPE].AppLayerTxMatch = DetectMQTTTypeMatch;
58 sigmatch_table[DETECT_AL_MQTT_TYPE].Setup = DetectMQTTTypeSetup;
59 sigmatch_table[DETECT_AL_MQTT_TYPE].Free = DetectMQTTTypeFree;
60#ifdef UNITTESTS
61 sigmatch_table[DETECT_AL_MQTT_TYPE].RegisterTests = MQTTTypeRegisterTests;
62#endif
63
2320d628
VJ
64 DetectAppLayerInspectEngineRegister2("mqtt.type", ALPROTO_MQTT, SIG_FLAG_TOSERVER, 1,
65 DetectEngineInspectMQTTTypeGeneric, NULL);
c3136007
SS
66
67 mqtt_type_id = DetectBufferTypeGetByName("mqtt.type");
68}
69
2320d628
VJ
70static int DetectEngineInspectMQTTTypeGeneric(DetectEngineCtx *de_ctx,
71 DetectEngineThreadCtx *det_ctx, const struct DetectEngineAppInspectionEngine_ *engine,
72 const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
c3136007 73{
2320d628 74 return DetectEngineInspectGenericList(
84385549 75 de_ctx, det_ctx, s, engine->smd, f, flags, alstate, txv, tx_id);
c3136007
SS
76}
77
78/**
79 * \internal
80 * \brief Function to match control packet type of an MQTT Tx
81 *
82 * \param det_ctx Pointer to the pattern matcher thread.
83 * \param f Pointer to the current flow.
84 * \param flags Flags.
85 * \param state App layer state.
86 * \param txv Pointer to the transaction.
87 * \param s Pointer to the Signature.
88 * \param ctx Pointer to the sigmatch that we will cast into DetectMQTTTypeData.
89 *
90 * \retval 0 no match.
91 * \retval 1 match.
92 */
93static int DetectMQTTTypeMatch(DetectEngineThreadCtx *det_ctx,
94 Flow *f, uint8_t flags, void *state,
95 void *txv, const Signature *s,
96 const SigMatchCtx *ctx)
97{
98 const uint8_t *de = (const uint8_t *)ctx;
99
100 if (!de)
101 return 0;
102
103 return rs_mqtt_tx_has_type(txv, *de);
104}
105
106/**
107 * \internal
108 * \brief This function is used to parse options passed via mqtt.type: keyword
109 *
110 * \param rawstr Pointer to the user provided options
111 *
112 * \retval de pointer to DetectMQTTTypeData on success
113 * \retval NULL on failure
114 */
115static uint8_t *DetectMQTTTypeParse(const char *rawstr)
116{
117 uint8_t *de = NULL;
118 int ret = 0;
119
120 ret = rs_mqtt_cstr_message_code(rawstr);
121 // negative value denotes invalid input
122 if(ret < 0) {
123 SCLogError(SC_ERR_UNKNOWN_VALUE, "unknown mqtt.type value %s", rawstr);
124 goto error;
125 }
126
127 de = SCMalloc(sizeof(uint8_t));
128 if (unlikely(de == NULL))
129 goto error;
130
131 *de = (uint8_t) ret;
132
133 return de;
134
135error:
136 if (de != NULL)
137 SCFree(de);
138 return NULL;
139}
140
141/**
142 * \internal
143 * \brief this function is used to add the parsed type query into the current signature
144 *
145 * \param de_ctx pointer to the Detection Engine Context
146 * \param s pointer to the Current Signature
147 * \param rawstr pointer to the user provided options
148 *
149 * \retval 0 on Success
150 * \retval -1 on Failure
151 */
152static int DetectMQTTTypeSetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
153{
154 uint8_t *de = NULL;
155 SigMatch *sm = NULL;
156
157 if (DetectSignatureSetAppProto(s, ALPROTO_MQTT) < 0)
158 return -1;
159
160 de = DetectMQTTTypeParse(rawstr);
161 if (de == NULL)
162 goto error;
163
164 sm = SigMatchAlloc();
165 if (sm == NULL)
166 goto error;
167
168 sm->type = DETECT_AL_MQTT_TYPE;
169 sm->ctx = (SigMatchCtx *)de;
170
171 SigMatchAppendSMToList(s, sm, mqtt_type_id);
172
173 return 0;
174
175error:
176 if (de != NULL)
177 SCFree(de);
178 if (sm != NULL)
179 SCFree(sm);
180 return -1;
181}
182
183/**
184 * \internal
185 * \brief this function will free memory associated with DetectMQTTTypeData
186 *
187 * \param de pointer to DetectMQTTTypeData
188 */
189void DetectMQTTTypeFree(DetectEngineCtx *de_ctx, void *de_ptr)
190{
191 if (de_ptr != NULL)
192 SCFree(de_ptr);
193}
194
195/*
196 * ONLY TESTS BELOW THIS COMMENT
197 */
198
199#ifdef UNITTESTS
200/**
201 * \test MQTTTypeTestParse01 is a test for a valid value
202 *
203 * \retval 1 on success
204 * \retval 0 on failure
205 */
206static int MQTTTypeTestParse01 (void)
207{
208 uint8_t *de = NULL;
209 de = DetectMQTTTypeParse("CONNECT");
210 FAIL_IF_NULL(de);
211 FAIL_IF_NOT(*de == 1);
212 DetectMQTTTypeFree(NULL, de);
213
214 de = DetectMQTTTypeParse("PINGRESP");
215 FAIL_IF_NULL(de);
216 FAIL_IF_NOT(*de == 13);
217 DetectMQTTTypeFree(NULL, de);
218
219 PASS;
220}
221
222/**
223 * \test MQTTTypeTestParse02 is a test for a valid value
224 *
225 * \retval 1 on success
226 * \retval 0 on failure
227 */
228static int MQTTTypeTestParse02 (void)
229{
230 uint8_t *de = NULL;
231 de = DetectMQTTTypeParse("auth");
232 FAIL_IF_NULL(de);
233 FAIL_IF_NOT(*de == 15);
234 DetectMQTTTypeFree(NULL, de);
235
236 PASS;
237}
238
239/**
240 * \test MQTTTypeTestParse03 is a test for an invalid value
241 *
242 * \retval 1 on success
243 * \retval 0 on failure
244 */
245static int MQTTTypeTestParse03 (void)
246{
247 uint8_t *de = NULL;
248 de = DetectMQTTTypeParse("invalidopt");
249 if (de) {
250 DetectMQTTTypeFree(NULL, de);
251 FAIL;
252 }
253
254 de = DetectMQTTTypeParse("unassigned");
255 if (de) {
256 DetectMQTTTypeFree(NULL, de);
257 FAIL;
258 }
259
260 PASS;
261}
262
263#endif /* UNITTESTS */
264
265/**
266 * \brief this function registers unit tests for MQTTType
267 */
268void MQTTTypeRegisterTests(void)
269{
270#ifdef UNITTESTS
271 UtRegisterTest("MQTTTypeTestParse01", MQTTTypeTestParse01);
272 UtRegisterTest("MQTTTypeTestParse02", MQTTTypeTestParse02);
273 UtRegisterTest("MQTTTypeTestParse03", MQTTTypeTestParse03);
274#endif /* UNITTESTS */
2320d628 275}