suricata
detect-fileext.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2012 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 Victor Julien <victor@inliniac.net>
22  * \author Pablo Rincon <pablo.rincon.crespo@gmail.com>
23  *
24  */
25 
26 #include "suricata-common.h"
27 #include "threads.h"
28 #include "debug.h"
29 #include "decode.h"
30 
31 #include "detect.h"
32 #include "detect-parse.h"
33 
34 #include "detect-engine.h"
35 #include "detect-engine-mpm.h"
36 #include "detect-engine-state.h"
37 
38 #include "flow.h"
39 #include "flow-var.h"
40 #include "flow-util.h"
41 
42 #include "util-debug.h"
43 #include "util-unittest.h"
44 #include "util-unittest-helper.h"
45 #include "util-spm-bm.h"
46 #include "util-print.h"
47 #include "util-memcmp.h"
48 
49 #include "app-layer.h"
50 
51 #include "stream-tcp.h"
52 #include "detect-fileext.h"
53 
54 static int DetectFileextMatch (DetectEngineThreadCtx *, Flow *,
55  uint8_t, File *, const Signature *, const SigMatchCtx *);
56 static int DetectFileextSetup (DetectEngineCtx *, Signature *, const char *);
57 static void DetectFileextRegisterTests(void);
58 static void DetectFileextFree(void *);
59 static int g_file_match_list_id = 0;
60 
61 /**
62  * \brief Registration function for keyword: fileext
63  */
65 {
66  sigmatch_table[DETECT_FILEEXT].name = "fileext";
67  sigmatch_table[DETECT_FILEEXT].desc = "match on the extension of a file name";
68  sigmatch_table[DETECT_FILEEXT].url = DOC_URL DOC_VERSION "/rules/file-keywords.html#fileext";
69  sigmatch_table[DETECT_FILEEXT].FileMatch = DetectFileextMatch;
70  sigmatch_table[DETECT_FILEEXT].Setup = DetectFileextSetup;
71  sigmatch_table[DETECT_FILEEXT].Free = DetectFileextFree;
72  sigmatch_table[DETECT_FILEEXT].RegisterTests = DetectFileextRegisterTests;
75 
76  g_file_match_list_id = DetectBufferTypeRegister("files");
77 
78  SCLogDebug("registering fileext rule option");
79  return;
80 }
81 
82 /**
83  * \brief match the specified file extension
84  *
85  * \param t thread local vars
86  * \param det_ctx pattern matcher thread local data
87  * \param f *LOCKED* flow
88  * \param flags direction flags
89  * \param file file being inspected
90  * \param s signature being inspected
91  * \param m sigmatch that we will cast into DetectFileextData
92  *
93  * \retval 0 no match
94  * \retval 1 match
95  */
96 static int DetectFileextMatch (DetectEngineThreadCtx *det_ctx,
97  Flow *f, uint8_t flags, File *file, const Signature *s, const SigMatchCtx *m)
98 {
99  SCEnter();
100  int ret = 0;
101 
102  DetectFileextData *fileext = (DetectFileextData *)m;
103 
104  if (file->name == NULL)
105  SCReturnInt(0);
106 
107  if (file->name_len <= fileext->len)
108  SCReturnInt(0);
109 
110  int offset = file->name_len - fileext->len;
111 
112  /* fileext->ext is already in lowercase, as SCMemcmpLowercase requires */
113  if (file->name[offset - 1] == '.' &&
114  SCMemcmpLowercase(fileext->ext, file->name + offset, fileext->len) == 0)
115  {
116  if (!(fileext->flags & DETECT_CONTENT_NEGATED)) {
117  ret = 1;
118  SCLogDebug("File ext found");
119  }
120  } else if (fileext->flags & DETECT_CONTENT_NEGATED) {
121  SCLogDebug("negated match");
122  ret = 1;
123  }
124 
125  SCReturnInt(ret);
126 }
127 
128 /**
129  * \brief This function is used to parse fileet
130  *
131  * \param str Pointer to the fileext value string
132  *
133  * \retval pointer to DetectFileextData on success
134  * \retval NULL on failure
135  */
136 static DetectFileextData *DetectFileextParse (const char *str, bool negate)
137 {
138  DetectFileextData *fileext = NULL;
139 
140  /* We have a correct filename option */
141  fileext = SCMalloc(sizeof(DetectFileextData));
142  if (unlikely(fileext == NULL))
143  goto error;
144 
145  memset(fileext, 0x00, sizeof(DetectFileextData));
146 
147  if (DetectContentDataParse("fileext", str, &fileext->ext, &fileext->len) == -1) {
148  goto error;
149  }
150  uint16_t u;
151  for (u = 0; u < fileext->len; u++)
152  fileext->ext[u] = tolower(fileext->ext[u]);
153 
154  if (negate) {
155  fileext->flags |= DETECT_CONTENT_NEGATED;
156  }
157 
158  SCLogDebug("flags %02X", fileext->flags);
159  if (fileext->flags & DETECT_CONTENT_NEGATED) {
160  SCLogDebug("negated fileext");
161  }
162 
163 #ifdef DEBUG
164  if (SCLogDebugEnabled()) {
165  char *ext = SCMalloc(fileext->len + 1);
166  if (ext != NULL) {
167  memcpy(ext, fileext->ext, fileext->len);
168  ext[fileext->len] = '\0';
169  SCLogDebug("will look for fileext %s", ext);
170  SCFree(ext);
171  }
172  }
173 #endif
174 
175  return fileext;
176 
177 error:
178  if (fileext != NULL)
179  DetectFileextFree(fileext);
180  return NULL;
181 
182 }
183 
184 /**
185  * \brief this function is used to add the parsed "id" option
186  * into the current signature
187  *
188  * \param de_ctx pointer to the Detection Engine Context
189  * \param s pointer to the Current Signature
190  * \param idstr pointer to the user provided "id" option
191  *
192  * \retval 0 on Success
193  * \retval -1 on Failure
194  */
195 static int DetectFileextSetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
196 {
197  DetectFileextData *fileext= NULL;
198  SigMatch *sm = NULL;
199 
200  fileext = DetectFileextParse(str, s->init_data->negated);
201  if (fileext == NULL)
202  goto error;
203 
204  /* Okay so far so good, lets get this into a SigMatch
205  * and put it in the Signature. */
206  sm = SigMatchAlloc();
207  if (sm == NULL)
208  goto error;
209 
210  sm->type = DETECT_FILEEXT;
211  sm->ctx = (void *)fileext;
212 
213  SigMatchAppendSMToList(s, sm, g_file_match_list_id);
214 
216  return 0;
217 
218 error:
219  if (fileext != NULL)
220  DetectFileextFree(fileext);
221  if (sm != NULL)
222  SCFree(sm);
223  return -1;
224 
225 }
226 
227 /**
228  * \brief this function will free memory associated with DetectFileextData
229  *
230  * \param fileext pointer to DetectFileextData
231  */
232 static void DetectFileextFree(void *ptr)
233 {
234  if (ptr != NULL) {
235  DetectFileextData *fileext = (DetectFileextData *)ptr;
236  if (fileext->ext != NULL)
237  SCFree(fileext->ext);
238  SCFree(fileext);
239  }
240 }
241 
242 #ifdef UNITTESTS /* UNITTESTS */
243 
244 /**
245  * \test DetectFileextTestParse01
246  */
247 static int DetectFileextTestParse01 (void)
248 {
249  DetectFileextData *dfd = DetectFileextParse("doc", false);
250  if (dfd != NULL) {
251  DetectFileextFree(dfd);
252  return 1;
253  }
254  return 0;
255 }
256 
257 /**
258  * \test DetectFileextTestParse02
259  */
260 static int DetectFileextTestParse02 (void)
261 {
262  int result = 0;
263 
264  DetectFileextData *dfd = DetectFileextParse("tar.gz", false);
265  if (dfd != NULL) {
266  if (dfd->len == 6 && memcmp(dfd->ext, "tar.gz", 6) == 0) {
267  result = 1;
268  }
269 
270  DetectFileextFree(dfd);
271  return result;
272  }
273  return 0;
274 }
275 
276 /**
277  * \test DetectFileextTestParse03
278  */
279 static int DetectFileextTestParse03 (void)
280 {
281  int result = 0;
282 
283  DetectFileextData *dfd = DetectFileextParse("pdf", false);
284  if (dfd != NULL) {
285  if (dfd->len == 3 && memcmp(dfd->ext, "pdf", 3) == 0) {
286  result = 1;
287  }
288 
289  DetectFileextFree(dfd);
290  return result;
291  }
292  return 0;
293 }
294 
295 #endif /* UNITTESTS */
296 
297 /**
298  * \brief this function registers unit tests for DetectFileext
299  */
300 void DetectFileextRegisterTests(void)
301 {
302 #ifdef UNITTESTS /* UNITTESTS */
303  UtRegisterTest("DetectFileextTestParse01", DetectFileextTestParse01);
304  UtRegisterTest("DetectFileextTestParse02", DetectFileextTestParse02);
305  UtRegisterTest("DetectFileextTestParse03", DetectFileextTestParse03);
306 #endif /* UNITTESTS */
307 }
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect.h:1448
SignatureInitData * init_data
Definition: detect.h:591
uint16_t flags
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1186
#define SCLogDebug(...)
Definition: util-debug.h:335
#define unlikely(expr)
Definition: util-optimize.h:35
int DetectContentDataParse(const char *keyword, const char *contentstr, uint8_t **pstr, uint16_t *plen)
Parse a content string, ie "abc|DE|fgh".
uint64_t offset
#define FILE_SIG_NEED_FILENAME
Definition: detect.h:283
void DetectFileextRegister(void)
Registration function for keyword: fileext.
const char * name
Definition: detect.h:1200
Signature container.
Definition: detect.h:522
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:313
main detection engine ctx
Definition: detect.h:761
int SCLogDebugEnabled(void)
Returns whether debug messages are enabled to be logged or not.
Definition: util-debug.c:624
#define str(s)
int(* FileMatch)(DetectEngineThreadCtx *, Flow *, uint8_t flags, File *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1178
Data structures and function prototypes for keeping state for the detection engine.
void(* Free)(void *)
Definition: detect.h:1191
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define SIGMATCH_QUOTES_OPTIONAL
Definition: detect.h:1381
#define SCEnter(...)
Definition: util-debug.h:337
uint16_t name_len
Definition: util-file.h:66
uint16_t alternative
Definition: detect.h:1198
uint8_t type
Definition: detect.h:319
#define SCReturnInt(x)
Definition: util-debug.h:341
#define FILE_SIG_NEED_FILE
Definition: detect.h:282
const char * desc
Definition: detect.h:1202
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:346
int DetectBufferTypeRegister(const char *name)
SigMatchCtx * ctx
Definition: detect.h:321
#define SCMalloc(a)
Definition: util-mem.h:222
#define DETECT_CONTENT_NEGATED
#define SCFree(a)
Definition: util-mem.h:322
const char * url
Definition: detect.h:1203
SCMutex m
Definition: flow-hash.h:105
#define DOC_URL
Definition: suricata.h:86
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:232
uint8_t file_flags
Definition: detect.h:536
#define SIGMATCH_HANDLE_NEGATION
Definition: detect.h:1389
#define DOC_VERSION
Definition: suricata.h:91
uint16_t flags
Definition: detect.h:1194
Flow data structure.
Definition: flow.h:325
uint8_t * name
Definition: util-file.h:75
void(* RegisterTests)(void)
Definition: detect.h:1192
a single match condition for a signature
Definition: detect.h:318