1 /*
2  ** Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3  ** Copyright (C) 1998-2013 Sourcefire, Inc.
4  **
5  ** This program is free software; you can redistribute it and/or modify
6  ** it under the terms of the GNU General Public License Version 2 as
7  ** published by the Free Software Foundation.  You may not use, modify or
8  ** distribute this program under any other version of the GNU General
9  ** Public License.
10  **
11  ** This program is distributed in the hope that it will be useful,
12  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  ** GNU General Public License for more details.
15  **
16  ** You should have received a copy of the GNU General Public License
17  ** along with this program; if not, write to the Free Software
18  ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20 
21 /* sp_file_data
22  *
23  */
24 
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28 
29 #include <sys/types.h>
30 #include <stdlib.h>
31 #include <ctype.h>
32 #ifdef HAVE_STRINGS_H
33 #include <strings.h>
34 #endif
35 #include <errno.h>
36 
37 #include "sf_types.h"
38 #include "snort_bounds.h"
39 #include "rules.h"
40 #include "decode.h"
41 #include "plugbase.h"
42 #include "parser.h"
43 #include "snort_debug.h"
44 #include "util.h"
45 #include "mstring.h"
46 
47 #include "snort.h"
48 #include "profiler.h"
49 #include "sp_file_data.h"
50 #ifdef PERF_PROFILING
51 PreprocStats fileDataPerfStats;
52 extern PreprocStats ruleOTNEvalPerfStats;
53 #endif
54 
55 #include "detection_options.h"
56 #include "detection_util.h"
57 
58 extern char *file_name;  /* this is the file name from rules.c, generally used
59                             for error messages */
60 
61 extern int file_line;    /* this is the file line number from rules.c that is
62                             used to indicate file lines for error messages */
63 
64 static void FileDataInit(struct _SnortConfig *, char *, OptTreeNode *, int);
65 void FileDataParse(char *, FileData *, OptTreeNode *);
66 int  FileDataEval(void *option_data, Packet *p);
67 
FileDataHash(void * d)68 uint32_t FileDataHash(void *d)
69 {
70     uint32_t a,b,c;
71 
72     FileData *data = (FileData *)d;
73 
74     a = data->mime_decode_flag;
75     b = RULE_OPTION_TYPE_FILE_DATA;
76     c = 0;
77 
78     final(a,b,c);
79 
80     return c;
81 }
82 
FileDataCompare(void * l,void * r)83 int FileDataCompare(void *l, void *r)
84 {
85     FileData *left = (FileData *)l;
86     FileData *right = (FileData *)r;
87     if (!left || !right)
88         return DETECTION_OPTION_NOT_EQUAL;
89     if( left->mime_decode_flag == right->mime_decode_flag )
90         return DETECTION_OPTION_EQUAL;
91 
92     return DETECTION_OPTION_NOT_EQUAL;
93 }
94 
95 
96 
97 /****************************************************************************
98  *
99  * Function: SetupFileData()
100  *
101  * Purpose: Load 'er up
102  *
103  * Arguments: None.
104  *
105  * Returns: void function
106  *
107  ****************************************************************************/
SetupFileData(void)108 void SetupFileData(void)
109 {
110     /* map the keyword to an initialization/processing function */
111     RegisterRuleOption("file_data", FileDataInit, NULL, OPT_TYPE_DETECTION, NULL);
112 #ifdef PERF_PROFILING
113     RegisterPreprocessorProfile("file_data", &fileDataPerfStats, 3, &ruleOTNEvalPerfStats, NULL);
114 #endif
115 
116     DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: file_data Setup\n"););
117 }
118 
119 
120 /****************************************************************************
121  *
122  * Function: FileDataInit(struct _SnortConfig *, char *, OptTreeNode *, int protocol)
123  *
124  * Purpose: Generic rule configuration function.  Handles parsing the rule
125  *          information and attaching the associated detection function to
126  *          the OTN.
127  *
128  * Arguments: data => rule arguments/data
129  *            otn => pointer to the current rule option list node
130  *            protocol => protocol the rule is on (we don't care in this case)
131  *
132  * Returns: void function
133  *
134  ****************************************************************************/
FileDataInit(struct _SnortConfig * sc,char * data,OptTreeNode * otn,int protocol)135 static void FileDataInit(struct _SnortConfig *sc, char *data, OptTreeNode *otn, int protocol)
136 {
137     FileData *idx;
138     OptFpList *fpl;
139     void *idx_dup;
140 
141     idx = (FileData *) SnortAlloc(sizeof(FileData));
142 
143     if(idx == NULL)
144     {
145         FatalError("%s(%d): Unable to allocate file_data node\n",
146                     file_name, file_line);
147     }
148 
149 
150 
151     otn->ds_list[PLUGIN_FILE_DATA] = (void *)1;
152 
153     FileDataParse(data, idx, otn);
154 
155     if (add_detection_option(sc, RULE_OPTION_TYPE_FILE_DATA, (void *)idx, &idx_dup) == DETECTION_OPTION_EQUAL)
156     {
157         free(idx);
158         idx = idx_dup;
159     }
160 
161     fpl = AddOptFuncToList(FileDataEval, otn);
162     fpl->type = RULE_OPTION_TYPE_FILE_DATA;
163     fpl->context = (void *)idx;
164 
165     return;
166 }
167 
168 
169 
170 /****************************************************************************
171  *
172  * Function: FileDataParse(char *, OptTreeNode *)
173  *
174  * Purpose: This is the function that is used to process the option keyword's
175  *          arguments and attach them to the rule's data structures.
176  *
177  * Arguments: data => argument data
178  *            otn => pointer to the current rule's OTN
179  *
180  * Returns: void function
181  *
182  ****************************************************************************/
FileDataParse(char * data,FileData * idx,OptTreeNode * otn)183 void FileDataParse(char *data, FileData *idx, OptTreeNode *otn)
184 {
185 
186     if (IsEmptyStr(data))
187     {
188         idx->mime_decode_flag = 0;
189     }
190     else if(!strcasecmp("mime",data))
191     {
192         ParseWarning("The argument 'mime' to 'file_data' rule option is deprecated.\n");
193     }
194     else
195     {
196         FatalError("%s(%d) file_data: Invalid token %s\n",
197                     file_name, file_line, data);
198     }
199 
200     return;
201 
202 }
203 
204 /****************************************************************************
205  *
206  * Function: FileDataEval(char *, OptTreeNode *, OptFpList *)
207  *
208  * Purpose: Use this function to perform the particular detection routine
209  *          that this rule keyword is supposed to encompass.
210  *
211  * Arguments: p => pointer to the decoded packet
212  *            otn => pointer to the current rule's OTN
213  *            fp_list => pointer to the function pointer list
214  *
215  * Returns: If the detection test fails, this function *must* return a zero!
216  *          On success, it calls the next function in the detection list
217  *
218  ****************************************************************************/
FileDataEval(void * option_data,Packet * p)219 int FileDataEval(void *option_data, Packet *p)
220 {
221     int rval = DETECTION_OPTION_NO_MATCH;
222     const uint8_t *data;
223     uint16_t len;
224     FileData *idx;
225     PROFILE_VARS;
226 
227     PREPROC_PROFILE_START(fileDataPerfStats);
228     idx = (FileData *)option_data;
229 
230     data = file_data_ptr.data;
231     len = file_data_ptr.len;
232 
233     if ((p->dsize == 0) || !idx)
234     {
235         PREPROC_PROFILE_END(fileDataPerfStats);
236         return rval;
237     }
238 
239     if ((data == NULL)|| (len == 0))
240     {
241         data = p->data;
242         len = p->dsize;
243     }
244 
245     if(idx->mime_decode_flag)
246         mime_present = 1;
247     else
248         mime_present = 0;
249 
250     SetDoePtr(data,  DOE_BUF_STD);
251     SetAltDetect(data, len);
252     rval = DETECTION_OPTION_MATCH;
253 
254     PREPROC_PROFILE_END(fileDataPerfStats);
255     return rval;
256 }
257