suricata
detect-ssl-state.c
Go to the documentation of this file.
1/* Copyright (C) 2007-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 Anoop Saldanha <anoopsaldanha@gmail.com>
22 *
23 * Implements support for ssl_state keyword.
24 */
25
26#include "suricata-common.h"
27#include "threads.h"
28#include "decode.h"
29
30#include "detect.h"
31#include "detect-parse.h"
32
33#include "detect-engine.h"
34#include "detect-engine-mpm.h"
35#include "detect-engine-state.h"
36
37#include "flow.h"
38#include "flow-var.h"
39#include "flow-util.h"
40
41#include "util-debug.h"
42#include "util-unittest.h"
44
45#include "app-layer.h"
46#include "app-layer-parser.h"
47
48#include "detect-ssl-state.h"
49
50#include "stream-tcp.h"
51#include "app-layer-ssl.h"
52
53#define PARSE_REGEX1 "^(!?)([_a-zA-Z0-9]+)(.*)$"
54static DetectParseRegex parse_regex1;
55
56#define PARSE_REGEX2 "^(?:\\s*[|,]\\s*(!?)([_a-zA-Z0-9]+))(.*)$"
57static DetectParseRegex parse_regex2;
58
59static int DetectSslStateMatch(DetectEngineThreadCtx *,
60 Flow *, uint8_t, void *, void *,
61 const Signature *, const SigMatchCtx *);
62static int DetectSslStateSetup(DetectEngineCtx *, Signature *, const char *);
63#ifdef UNITTESTS
64static void DetectSslStateRegisterTests(void);
65#endif
66static void DetectSslStateFree(DetectEngineCtx *, void *);
67
68static int g_tls_generic_list_id = 0;
69
70/**
71 * \brief Registers the keyword handlers for the "ssl_state" keyword.
72 */
74{
76 sigmatch_table[DETECT_SSL_STATE].desc = "match the state of the SSL connection";
77 sigmatch_table[DETECT_SSL_STATE].url = "/rules/tls-keywords.html#ssl-state";
78 sigmatch_table[DETECT_SSL_STATE].AppLayerTxMatch = DetectSslStateMatch;
79 sigmatch_table[DETECT_SSL_STATE].Setup = DetectSslStateSetup;
80 sigmatch_table[DETECT_SSL_STATE].Free = DetectSslStateFree;
81#ifdef UNITTESTS
82 sigmatch_table[DETECT_SSL_STATE].RegisterTests = DetectSslStateRegisterTests;
83#endif
86
87 g_tls_generic_list_id = DetectBufferTypeRegister("tls_generic");
88
90 "generic ssl/tls inspection");
91
96}
97
98/**
99 * \brief App layer match function ssl_state keyword.
100 *
101 * \param tv Pointer to threadvars.
102 * \param det_ctx Pointer to the thread's detection context.
103 * \param f Pointer to the flow.
104 * \param flags Flags.
105 * \param state App layer state.
106 * \param s Sig we are currently inspecting.
107 * \param m SigMatch we are currently inspecting.
108 *
109 * \retval 1 Match.
110 * \retval 0 No match.
111 */
112static int DetectSslStateMatch(DetectEngineThreadCtx *det_ctx,
113 Flow *f, uint8_t flags, void *alstate, void *txv,
114 const Signature *s, const SigMatchCtx *m)
115{
116 const DetectSslStateData *ssd = (const DetectSslStateData *)m;
117 SSLState *ssl_state = (SSLState *)alstate;
118 if (ssl_state == NULL) {
119 SCLogDebug("no app state, no match");
120 return 0;
121 }
122
123 uint32_t ssl_flags = ssl_state->current_flags;
124
125 if ((ssd->flags & ssl_flags) ^ ssd->mask) {
126 return 1;
127 }
128
129 return 0;
130}
131
132/**
133 * \brief Parse the arg supplied with ssl_state and return it in a
134 * DetectSslStateData instance.
135 *
136 * \param arg Pointer to the string to be parsed.
137 *
138 * \retval ssd Pointer to DetectSslStateData on success.
139 * \retval NULL On failure.
140 */
141static DetectSslStateData *DetectSslStateParse(const char *arg)
142{
143 size_t pcre2len;
144 char str1[64];
145 char str2[64];
146 int negate = 0;
147 uint32_t flags = 0, mask = 0;
148 DetectSslStateData *ssd = NULL;
149
150 pcre2_match_data *match = NULL;
151 int ret = DetectParsePcreExec(&parse_regex1, &match, arg, 0, 0);
152 if (ret < 1) {
153 SCLogError("Invalid arg \"%s\" supplied to "
154 "ssl_state keyword.",
155 arg);
156 goto error;
157 }
158
159 pcre2len = sizeof(str1);
160 int res = pcre2_substring_copy_bynumber(match, 1, (PCRE2_UCHAR8 *)str1, &pcre2len);
161 if (res < 0) {
162 SCLogError("pcre2_substring_copy_bynumber failed");
163 goto error;
164 }
165 negate = !strcmp("!", str1);
166
167 pcre2len = sizeof(str1);
168 res = pcre2_substring_copy_bynumber(match, 2, (PCRE2_UCHAR8 *)str1, &pcre2len);
169 if (res < 0) {
170 SCLogError("pcre2_substring_copy_bynumber failed");
171 goto error;
172 }
173
174 if (strcmp("client_hello", str1) == 0) {
176 if (negate)
178 } else if (strcmp("server_hello", str1) == 0) {
180 if (negate)
182 } else if (strcmp("client_keyx", str1) == 0) {
184 if (negate)
186 } else if (strcmp("server_keyx", str1) == 0) {
188 if (negate)
190 } else if (strcmp("unknown", str1) == 0) {
192 if (negate)
194 } else {
195 SCLogError("Found invalid option \"%s\" "
196 "in ssl_state keyword.",
197 str1);
198 goto error;
199 }
200
201 pcre2len = sizeof(str1);
202 res = pcre2_substring_copy_bynumber(match, 3, (PCRE2_UCHAR8 *)str1, &pcre2len);
203 if (res < 0) {
204 SCLogError("pcre2_substring_copy_bynumber failed");
205 goto error;
206 }
207 while (res >= 0 && strlen(str1) > 0) {
208 pcre2_match_data *match2 = NULL;
209 ret = DetectParsePcreExec(&parse_regex2, &match2, str1, 0, 0);
210 if (ret < 1) {
211 SCLogError("Invalid arg \"%s\" supplied to "
212 "ssl_state keyword.",
213 arg);
214 if (match2) {
215 pcre2_match_data_free(match2);
216 }
217 goto error;
218 }
219
220 pcre2len = sizeof(str2);
221 res = pcre2_substring_copy_bynumber(match2, 1, (PCRE2_UCHAR8 *)str2, &pcre2len);
222 if (res < 0) {
223 SCLogError("pcre2_substring_copy_bynumber failed");
224 pcre2_match_data_free(match2);
225 goto error;
226 }
227 negate = !strcmp("!", str2);
228
229 pcre2len = sizeof(str2);
230 res = pcre2_substring_copy_bynumber(match2, 2, (PCRE2_UCHAR8 *)str2, &pcre2len);
231 if (res < 0) {
232 SCLogError("pcre2_substring_copy_bynumber failed");
233 pcre2_match_data_free(match2);
234 goto error;
235 }
236 if (strcmp("client_hello", str2) == 0) {
238 if (negate)
240 } else if (strcmp("server_hello", str2) == 0) {
242 if (negate)
244 } else if (strcmp("client_keyx", str2) == 0) {
246 if (negate)
248 } else if (strcmp("server_keyx", str2) == 0) {
250 if (negate)
252 } else if (strcmp("unknown", str2) == 0) {
254 if (negate)
256 } else {
257 SCLogError("Found invalid option \"%s\" "
258 "in ssl_state keyword.",
259 str2);
260 pcre2_match_data_free(match2);
261 goto error;
262 }
263
264 pcre2len = sizeof(str2);
265 res = pcre2_substring_copy_bynumber(match2, 3, (PCRE2_UCHAR8 *)str2, &pcre2len);
266 if (res < 0) {
267 SCLogError("pcre2_substring_copy_bynumber failed");
268 pcre2_match_data_free(match2);
269 goto error;
270 }
271
272 memcpy(str1, str2, sizeof(str1));
273 pcre2_match_data_free(match2);
274 }
275
276 if ( (ssd = SCMalloc(sizeof(DetectSslStateData))) == NULL) {
277 goto error;
278 }
279 ssd->flags = flags;
280 ssd->mask = mask;
281
282 pcre2_match_data_free(match);
283 return ssd;
284
285error:
286 if (match) {
287 pcre2_match_data_free(match);
288 }
289 return NULL;
290}
291
292 /**
293 * \internal
294 * \brief Setup function for ssl_state keyword.
295 *
296 * \param de_ctx Pointer to the Detection Engine Context.
297 * \param s Pointer to the Current Signature
298 * \param arg String holding the arg.
299 *
300 * \retval 0 On success.
301 * \retval -1 On failure.
302 */
303static int DetectSslStateSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
304{
305 DetectSslStateData *ssd = NULL;
306
308 return -1;
309
310 ssd = DetectSslStateParse(arg);
311 if (ssd == NULL)
312 goto error;
313
315 de_ctx, s, DETECT_SSL_STATE, (SigMatchCtx *)ssd, g_tls_generic_list_id) == NULL) {
316 goto error;
317 }
318 return 0;
319
320error:
321 if (ssd != NULL)
322 DetectSslStateFree(de_ctx, ssd);
323 return -1;
324}
325
326/**
327 * \brief Free memory associated with DetectSslStateData.
328 *
329 * \param ptr pointer to the data to be freed.
330 */
331static void DetectSslStateFree(DetectEngineCtx *de_ctx, void *ptr)
332{
333 if (ptr != NULL)
334 SCFree(ptr);
335}
336
337#ifdef UNITTESTS
339#endif
@ ALPROTO_TLS
uint8_t flags
Definition decode-gre.h:0
Data structures and function prototypes for keeping state for the detection engine.
int DetectBufferTypeRegister(const char *name)
void DetectBufferTypeSetDescriptionByName(const char *name, const char *desc)
void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uint32_t dir, int progress, InspectEngineFuncPtr Callback, InspectionBufferGetDataPtr GetData)
Registers an app inspection engine.
uint8_t DetectEngineInspectGenericList(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const struct DetectEngineAppInspectionEngine_ *engine, const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
Do the content inspection & validation for a signature.
void DetectSetupParseRegexes(const char *parse_str, DetectParseRegex *detect_parse)
int SCDetectSignatureSetAppProto(Signature *s, AppProto alproto)
int DetectParsePcreExec(DetectParseRegex *parse_regex, pcre2_match_data **match, const char *str, int start_offset, int options)
SigMatch * SCSigMatchAppendSMToList(DetectEngineCtx *de_ctx, Signature *s, uint16_t type, SigMatchCtx *ctx, const int list)
Append a SigMatch to the list type.
SigTableElmt * sigmatch_table
#define PARSE_REGEX2
void DetectSslStateRegister(void)
Registers the keyword handlers for the "ssl_state" keyword.
#define PARSE_REGEX1
#define DETECT_SSL_STATE_CLIENT_KEYX
#define DETECT_SSL_STATE_SERVER_HELLO
#define DETECT_SSL_STATE_UNKNOWN
#define DETECT_SSL_STATE_CLIENT_HELLO
#define DETECT_SSL_STATE_SERVER_KEYX
#define SIG_FLAG_TOCLIENT
Definition detect.h:272
#define SIG_FLAG_TOSERVER
Definition detect.h:271
SCMutex m
Definition flow-hash.h:6
DetectEngineCtx * de_ctx
main detection engine ctx
Definition detect.h:932
Flow data structure.
Definition flow.h:356
SSLv[2.0|3.[0|1|2|3]] state structure.
uint32_t current_flags
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition detect.h:351
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
const char * desc
Definition detect.h:1461
int(* AppLayerTxMatch)(DetectEngineThreadCtx *, Flow *, uint8_t flags, void *alstate, void *txv, const Signature *, const SigMatchCtx *)
Definition detect.h:1424
void(* RegisterTests)(void)
Definition detect.h:1448
const char * name
Definition detect.h:1459
Signature container.
Definition detect.h:668
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
#define SCMalloc(sz)
Definition util-mem.h:47
#define SCFree(p)
Definition util-mem.h:61