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 (ThreadVars *, 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;
74 
75  g_file_match_list_id = DetectBufferTypeRegister("files");
76 
77  SCLogDebug("registering fileext rule option");
78  return;
79 }
80 
81 /**
82  * \brief match the specified file extension
83  *
84  * \param t thread local vars
85  * \param det_ctx pattern matcher thread local data
86  * \param f *LOCKED* flow
87  * \param flags direction flags
88  * \param file file being inspected
89  * \param s signature being inspected
90  * \param m sigmatch that we will cast into DetectFileextData
91  *
92  * \retval 0 no match
93  * \retval 1 match
94  */
95 static int DetectFileextMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx,
96  Flow *f, uint8_t flags, File *file, const Signature *s, const SigMatchCtx *m)
97 {
98  SCEnter();
99  int ret = 0;
100 
101  DetectFileextData *fileext = (DetectFileextData *)m;
102 
103  if (file->name == NULL)
104  SCReturnInt(0);
105 
106  if (file->name_len <= fileext->len)
107  SCReturnInt(0);
108 
109  int offset = file->name_len - fileext->len;
110 
111  /* fileext->ext is already in lowercase, as SCMemcmpLowercase requires */
112  if (file->name[offset - 1] == '.' &&
113  SCMemcmpLowercase(fileext->ext, file->name + offset, fileext->len) == 0)
114  {
115  if (!(fileext->flags & DETECT_CONTENT_NEGATED)) {
116  ret = 1;
117  SCLogDebug("File ext found");
118  }
119  } else if (fileext->flags & DETECT_CONTENT_NEGATED) {
120  SCLogDebug("negated match");
121  ret = 1;
122  }
123 
124  SCReturnInt(ret);
125 }
126 
127 /**
128  * \brief This function is used to parse fileet
129  *
130  * \param str Pointer to the fileext value string
131  *
132  * \retval pointer to DetectFileextData on success
133  * \retval NULL on failure
134  */
135 static DetectFileextData *DetectFileextParse (const char *str, bool negate)
136 {
137  DetectFileextData *fileext = NULL;
138 
139  /* We have a correct filename option */
140  fileext = SCMalloc(sizeof(DetectFileextData));
141  if (unlikely(fileext == NULL))
142  goto error;
143 
144  memset(fileext, 0x00, sizeof(DetectFileextData));
145 
146  if (DetectContentDataParse("fileext", str, &fileext->ext, &fileext->len) == -1) {
147  goto error;
148  }
149  uint16_t u;
150  for (u = 0; u < fileext->len; u++)
151  fileext->ext[u] = tolower(fileext->ext[u]);
152 
153  if (negate) {
154  fileext->flags |= DETECT_CONTENT_NEGATED;
155  }
156 
157  SCLogDebug("flags %02X", fileext->flags);
158  if (fileext->flags & DETECT_CONTENT_NEGATED) {
159  SCLogDebug("negated fileext");
160  }
161 
162 #ifdef DEBUG
163  if (SCLogDebugEnabled()) {
164  char *ext = SCMalloc(fileext->len + 1);
165  if (ext != NULL) {
166  memcpy(ext, fileext->ext, fileext->len);
167  ext[fileext->len] = '\0';
168  SCLogDebug("will look for fileext %s", ext);
169  SCFree(ext);
170  }
171  }
172 #endif
173 
174  return fileext;
175 
176 error:
177  if (fileext != NULL)
178  DetectFileextFree(fileext);
179  return NULL;
180 
181 }
182 
183 /**
184  * \brief this function is used to add the parsed "id" option
185  * into the current signature
186  *
187  * \param de_ctx pointer to the Detection Engine Context
188  * \param s pointer to the Current Signature
189  * \param idstr pointer to the user provided "id" option
190  *
191  * \retval 0 on Success
192  * \retval -1 on Failure
193  */
194 static int DetectFileextSetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
195 {
196  DetectFileextData *fileext= NULL;
197  SigMatch *sm = NULL;
198 
199  fileext = DetectFileextParse(str, s->init_data->negated);
200  if (fileext == NULL)
201  goto error;
202 
203  /* Okay so far so good, lets get this into a SigMatch
204  * and put it in the Signature. */
205  sm = SigMatchAlloc();
206  if (sm == NULL)
207  goto error;
208 
209  sm->type = DETECT_FILEEXT;
210  sm->ctx = (void *)fileext;
211 
212  SigMatchAppendSMToList(s, sm, g_file_match_list_id);
213 
215  return 0;
216 
217 error:
218  if (fileext != NULL)
219  DetectFileextFree(fileext);
220  if (sm != NULL)
221  SCFree(sm);
222  return -1;
223 
224 }
225 
226 /**
227  * \brief this function will free memory associated with DetectFileextData
228  *
229  * \param fileext pointer to DetectFileextData
230  */
231 static void DetectFileextFree(void *ptr)
232 {
233  if (ptr != NULL) {
234  DetectFileextData *fileext = (DetectFileextData *)ptr;
235  if (fileext->ext != NULL)
236  SCFree(fileext->ext);
237  SCFree(fileext);
238  }
239 }
240 
241 #ifdef UNITTESTS /* UNITTESTS */
242 
243 /**
244  * \test DetectFileextTestParse01
245  */
246 static int DetectFileextTestParse01 (void)
247 {
248  DetectFileextData *dfd = DetectFileextParse("doc", false);
249  if (dfd != NULL) {
250  DetectFileextFree(dfd);
251  return 1;
252  }
253  return 0;
254 }
255 
256 /**
257  * \test DetectFileextTestParse02
258  */
259 static int DetectFileextTestParse02 (void)
260 {
261  int result = 0;
262 
263  DetectFileextData *dfd = DetectFileextParse("tar.gz", false);
264  if (dfd != NULL) {
265  if (dfd->len == 6 && memcmp(dfd->ext, "tar.gz", 6) == 0) {
266  result = 1;
267  }
268 
269  DetectFileextFree(dfd);
270  return result;
271  }
272  return 0;
273 }
274 
275 /**
276  * \test DetectFileextTestParse03
277  */
278 static int DetectFileextTestParse03 (void)
279 {
280  int result = 0;
281 
282  DetectFileextData *dfd = DetectFileextParse("pdf", false);
283  if (dfd != NULL) {
284  if (dfd->len == 3 && memcmp(dfd->ext, "pdf", 3) == 0) {
285  result = 1;
286  }
287 
288  DetectFileextFree(dfd);
289  return result;
290  }
291  return 0;
292 }
293 
294 #endif /* UNITTESTS */
295 
296 /**
297  * \brief this function registers unit tests for DetectFileext
298  */
299 void DetectFileextRegisterTests(void)
300 {
301 #ifdef UNITTESTS /* UNITTESTS */
302  UtRegisterTest("DetectFileextTestParse01", DetectFileextTestParse01);
303  UtRegisterTest("DetectFileextTestParse02", DetectFileextTestParse02);
304  UtRegisterTest("DetectFileextTestParse03", DetectFileextTestParse03);
305 #endif /* UNITTESTS */
306 }
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect.h:1406
SignatureInitData * init_data
Definition: detect.h:563
uint16_t flags
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1149
#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:287
void DetectFileextRegister(void)
Registration function for keyword: fileext.
const char * name
Definition: detect.h:1163
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
int SCLogDebugEnabled(void)
Returns whether debug messages are enabled to be logged or not.
Definition: util-debug.c:631
#define str(s)
int(* FileMatch)(ThreadVars *, DetectEngineThreadCtx *, Flow *, uint8_t flags, File *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1140
Data structures and function prototypes for keeping state for the detection engine.
void(* Free)(void *)
Definition: detect.h:1154
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define SIGMATCH_QUOTES_OPTIONAL
Definition: detect.h:1343
#define SCEnter(...)
Definition: util-debug.h:337
uint16_t name_len
Definition: util-file.h:66
uint8_t type
Definition: detect.h:323
#define SCReturnInt(x)
Definition: util-debug.h:341
#define FILE_SIG_NEED_FILE
Definition: detect.h:286
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 DETECT_CONTENT_NEGATED
#define SCFree(a)
Definition: util-mem.h:228
const char * url
Definition: detect.h:1166
SCMutex m
Definition: flow-hash.h:105
#define DOC_URL
Definition: suricata.h:86
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:232
Per thread variable structure.
Definition: threadvars.h:57
uint8_t file_flags
Definition: detect.h:509
#define SIGMATCH_HANDLE_NEGATION
Definition: detect.h:1351
#define DOC_VERSION
Definition: suricata.h:91
uint16_t flags
Definition: detect.h:1157
Flow data structure.
Definition: flow.h:324
uint8_t * name
Definition: util-file.h:75
void(* RegisterTests)(void)
Definition: detect.h:1155
a single match condition for a signature
Definition: detect.h:322