suricata
detect-krb5-msgtype.c
Go to the documentation of this file.
1 /* Copyright (C) 2018 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 Pierre Chifflier <chifflier@wzdftpd.net>
22  */
23 
24 #include "suricata-common.h"
25 #include "util-unittest.h"
26 
27 #include "detect-parse.h"
28 #include "detect-engine.h"
29 
30 #include "detect-krb5-msgtype.h"
31 
32 #ifdef HAVE_RUST
33 
34 #include "app-layer-krb5.h"
35 #include "rust-krb-detect-gen.h"
36 
37 /**
38  * \brief Regex for parsing our keyword options
39  */
40 #define PARSE_REGEX "^\\s*([A-z0-9\\.]+|\"[A-z0-9_\\.]+\")\\s*$"
41 static pcre *parse_regex;
42 static pcre_extra *parse_regex_study;
43 
44 /* Prototypes of functions registered in DetectKrb5MsgTypeRegister below */
45 static int DetectKrb5MsgTypeMatch (ThreadVars *, DetectEngineThreadCtx *, Flow *,
46  uint8_t, void *, void *, const Signature *,
47  const SigMatchCtx *);
48 static int DetectKrb5MsgTypeSetup (DetectEngineCtx *, Signature *, const char *);
49 static void DetectKrb5MsgTypeFree (void *);
50 static void DetectKrb5MsgTypeRegisterTests (void);
51 
52 static int DetectEngineInspectKRB5Generic(ThreadVars *tv,
53  DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
54  const Signature *s, const SigMatchData *smd,
55  Flow *f, uint8_t flags, void *alstate,
56  void *txv, uint64_t tx_id);
57 
58 static int g_krb5_msg_type_list_id = 0;
59 
60 /**
61  * \brief Registration function for krb5_msg_type: keyword
62  *
63  * This function is called once in the 'lifetime' of the engine.
64  */
65 void DetectKrb5MsgTypeRegister(void) {
66  sigmatch_table[DETECT_AL_KRB5_MSGTYPE].name = "krb5_msg_type";
67  sigmatch_table[DETECT_AL_KRB5_MSGTYPE].desc = "match Kerberos 5 message type";
68  sigmatch_table[DETECT_AL_KRB5_MSGTYPE].url = DOC_URL DOC_VERSION "/rules/kerberos-keywords.html#krb5_msg_type";
70  sigmatch_table[DETECT_AL_KRB5_MSGTYPE].AppLayerTxMatch = DetectKrb5MsgTypeMatch;
71  sigmatch_table[DETECT_AL_KRB5_MSGTYPE].Setup = DetectKrb5MsgTypeSetup;
72  sigmatch_table[DETECT_AL_KRB5_MSGTYPE].Free = DetectKrb5MsgTypeFree;
73  sigmatch_table[DETECT_AL_KRB5_MSGTYPE].RegisterTests = DetectKrb5MsgTypeRegisterTests;
74 
77  DetectEngineInspectKRB5Generic);
78 
81  DetectEngineInspectKRB5Generic);
82 
83  /* set up the PCRE for keyword parsing */
84  DetectSetupParseRegexes(PARSE_REGEX, &parse_regex, &parse_regex_study);
85 
86  g_krb5_msg_type_list_id = DetectBufferTypeRegister("krb5_msg_type");
87  SCLogDebug("g_krb5_msg_type_list_id %d", g_krb5_msg_type_list_id);
88 }
89 
90 static int DetectEngineInspectKRB5Generic(ThreadVars *tv,
91  DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
92  const Signature *s, const SigMatchData *smd,
93  Flow *f, uint8_t flags, void *alstate,
94  void *txv, uint64_t tx_id)
95 {
96  return DetectEngineInspectGenericList(tv, de_ctx, det_ctx, s, smd,
97  f, flags, alstate, txv, tx_id);
98 }
99 
100 /**
101  * \brief This function is used to match KRB5 rule option on a packet
102  *
103  * \param t pointer to thread vars
104  * \param det_ctx pointer to the pattern matcher thread
105  * \param p pointer to the current packet
106  * \param m pointer to the sigmatch with context that we will cast into DetectKrb5Data
107  *
108  * \retval 0 no match
109  * \retval 1 match
110  */
111 static int DetectKrb5MsgTypeMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx,
112  Flow *f, uint8_t flags, void *state,
113  void *txv, const Signature *s,
114  const SigMatchCtx *ctx)
115 {
116  uint32_t msg_type;
117  const DetectKrb5MsgTypeData *dd = (const DetectKrb5MsgTypeData *)ctx;
118 
119  SCEnter();
120 
121  rs_krb5_tx_get_msgtype(txv, &msg_type);
122 
123  if (dd->msg_type == msg_type)
124  SCReturnInt(1);
125 
126  SCReturnInt(0);
127 }
128 
129 /**
130  * \brief This function is used to parse options passed via krb5_msgtype: keyword
131  *
132  * \param krb5str Pointer to the user provided krb5_msg_type options
133  *
134  * \retval krb5d pointer to DetectKrb5Data on success
135  * \retval NULL on failure
136  */
137 static DetectKrb5MsgTypeData *DetectKrb5MsgTypeParse (const char *krb5str)
138 {
139  DetectKrb5MsgTypeData *krb5d = NULL;
140  char arg1[4] = "";
141 #define MAX_SUBSTRINGS 30
142  int ret = 0, res = 0;
143  int ov[MAX_SUBSTRINGS];
144 
145  ret = pcre_exec(parse_regex, parse_regex_study,
146  krb5str, strlen(krb5str),
147  0, 0, ov, MAX_SUBSTRINGS);
148  if (ret != 2) {
149  SCLogError(SC_ERR_PCRE_MATCH, "parse error, ret %" PRId32 "", ret);
150  goto error;
151  }
152 
153  res = pcre_copy_substring((char *) krb5str, ov, MAX_SUBSTRINGS, 1, arg1, sizeof(arg1));
154  if (res < 0) {
155  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
156  goto error;
157  }
158 
159  krb5d = SCMalloc(sizeof (DetectKrb5MsgTypeData));
160  if (unlikely(krb5d == NULL))
161  goto error;
162  krb5d->msg_type = (uint8_t)atoi(arg1);
163 
164  return krb5d;
165 
166 error:
167  if (krb5d)
168  SCFree(krb5d);
169  return NULL;
170 }
171 
172 /**
173  * \brief parse the options from the 'krb5_msg_type' keyword in the rule into
174  * the Signature data structure.
175  *
176  * \param de_ctx pointer to the Detection Engine Context
177  * \param s pointer to the Current Signature
178  * \param krb5str pointer to the user provided options
179  *
180  * \retval 0 on Success
181  * \retval -1 on Failure
182  */
183 static int DetectKrb5MsgTypeSetup (DetectEngineCtx *de_ctx, Signature *s, const char *krb5str)
184 {
185  DetectKrb5MsgTypeData *krb5d = NULL;
186  SigMatch *sm = NULL;
187 
189  return -1;
190 
191  krb5d = DetectKrb5MsgTypeParse(krb5str);
192  if (krb5d == NULL)
193  goto error;
194 
195  sm = SigMatchAlloc();
196  if (sm == NULL)
197  goto error;
198 
200  sm->ctx = (void *)krb5d;
201 
202  SigMatchAppendSMToList(s, sm, g_krb5_msg_type_list_id);
203 
204  return 0;
205 
206 error:
207  if (krb5d != NULL)
208  DetectKrb5MsgTypeFree(krb5d);
209  if (sm != NULL)
210  SCFree(sm);
211  return -1;
212 }
213 
214 /**
215  * \brief this function will free memory associated with DetectKrb5Data
216  *
217  * \param ptr pointer to DetectKrb5Data
218  */
219 static void DetectKrb5MsgTypeFree(void *ptr) {
221 
222  SCFree(krb5d);
223 }
224 
225 #ifdef UNITTESTS
226 
227 /**
228  * \test description of the test
229  */
230 
231 static int DetectKrb5MsgTypeParseTest01 (void)
232 {
233  DetectKrb5MsgTypeData *krb5d = DetectKrb5MsgTypeParse("10");
234  FAIL_IF_NULL(krb5d);
235  FAIL_IF(!(krb5d->msg_type == 10));
236  DetectKrb5MsgTypeFree(krb5d);
237  PASS;
238 }
239 
240 static int DetectKrb5MsgTypeSignatureTest01 (void)
241 {
243  FAIL_IF_NULL(de_ctx);
244 
245  Signature *sig = DetectEngineAppendSig(de_ctx, "alert krb5 any any -> any any (krb5_msg_type:10; sid:1; rev:1;)");
246  FAIL_IF_NULL(sig);
247 
248  DetectEngineCtxFree(de_ctx);
249  PASS;
250 }
251 
252 #endif /* UNITTESTS */
253 
254 /**
255  * \brief this function registers unit tests for DetectKrb5MsgType
256  */
257 static void DetectKrb5MsgTypeRegisterTests(void) {
258 #ifdef UNITTESTS
259  UtRegisterTest("DetectKrb5MsgTypeParseTest01", DetectKrb5MsgTypeParseTest01);
260  UtRegisterTest("DetectKrb5MsgTypeSignatureTest01",
261  DetectKrb5MsgTypeSignatureTest01);
262 #endif /* UNITTESTS */
263 }
264 
265 #else /* HAVE_RUST */
266 
268 {
269 }
270 
271 #endif /* HAVE_RUST */
Signature * DetectEngineAppendSig(DetectEngineCtx *de_ctx, const char *sigstr)
Parse and append a Signature into the Detection Engine Context signature list.
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect.h:1406
uint16_t flags
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1149
int(* AppLayerTxMatch)(ThreadVars *, DetectEngineThreadCtx *, Flow *, uint8_t flags, void *alstate, void *txv, const Signature *, const SigMatchCtx *)
Definition: detect.h:1135
#define SCLogDebug(...)
Definition: util-debug.h:335
#define MAX_SUBSTRINGS
int DetectSignatureSetAppProto(Signature *s, AppProto alproto)
#define PASS
Pass the test.
#define unlikely(expr)
Definition: util-optimize.h:35
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
Data needed for Match()
Definition: detect.h:331
const char * name
Definition: detect.h:1163
int DetectEngineInspectGenericList(ThreadVars *tv, const DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Flow *f, const uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
Do the content inspection & validation for a signature.
Signature container.
Definition: detect.h:495
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:317
main detection engine ctx
Definition: detect.h:723
#define SIG_FLAG_TOCLIENT
Definition: detect.h:242
void(* Free)(void *)
Definition: detect.h:1154
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
void DetectSetupParseRegexes(const char *parse_str, pcre **parse_regex, pcre_extra **parse_regex_study)
#define SIG_FLAG_TOSERVER
Definition: detect.h:241
#define SCEnter(...)
Definition: util-debug.h:337
uint8_t type
Definition: detect.h:323
#define SCReturnInt(x)
Definition: util-debug.h:341
const char * desc
Definition: detect.h:1165
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:288
int DetectBufferTypeRegister(const char *name)
SigMatchCtx * ctx
Definition: detect.h:325
#define SCMalloc(a)
Definition: util-mem.h:166
#define SCFree(a)
Definition: util-mem.h:228
PoolThreadReserved res
void DetectKrb5MsgTypeRegister(void)
uint16_t tx_id
int(* Match)(ThreadVars *, DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1132
const char * url
Definition: detect.h:1166
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
#define DOC_URL
Definition: suricata.h:86
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:232
Per thread variable structure.
Definition: threadvars.h:57
#define PARSE_REGEX
#define DOC_VERSION
Definition: suricata.h:91
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Flow data structure.
Definition: flow.h:325
void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uint32_t dir, int progress, InspectEngineFuncPtr Callback)
register inspect engine at start up time
void(* RegisterTests)(void)
Definition: detect.h:1155
a single match condition for a signature
Definition: detect.h:322
DetectEngineCtx * DetectEngineCtxInit(void)