1 /*
2 **
3 **
4 ** Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
5 ** Copyright (C) 2012-2013 Sourcefire, Inc.
6 **
7 ** This program is free software; you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License Version 2 as
9 ** published by the Free Software Foundation. You may not use, modify or
10 ** distribute this program under any other version of the GNU General
11 ** Public License.
12 **
13 ** This program is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ** GNU General Public License for more details.
17 **
18 ** You should have received a copy of the GNU General Public License
19 ** along with this program; if not, write to the Free Software
20 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 **
22 ** Author(s): Hui Cao <hcao@sourcefire.com>
23 **
24 ** NOTES
25 ** 5.25.2012 - Initial Source Code. Hcao
26 */
27
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31
32 #include <sys/types.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35
36 #include "sf_types.h"
37 #include "util.h"
38 #include "mstring.h"
39 #include "memory_stats.h"
40 #include "parser.h"
41
42 #include "file_service_config.h"
43 #include "file_config.h"
44 #include "file_lib.h"
45 #include "file_capture.h"
46 #include "file_ss.h"
47
48 #define FILE_SERVICE_OPT__TYPE_DEPTH "file_type_depth"
49 #define FILE_SERVICE_OPT__SIG_DEPTH "file_signature_depth"
50 #define FILE_SERVICE_OPT__BLOCK_TIMEOUT "file_block_timeout"
51 #define FILE_SERVICE_OPT__LOOKUP_TIMEOUT "file_lookup_timeout"
52 #define FILE_SERVICE_OPT__BLOCK_TIMEOUT_LOOKUP "block_timeout_lookup"
53 #define FILE_SERVICE_OPT__CAPTURE_MEMCAP "file_capture_memcap"
54 #define FILE_SERVICE_OPT__CAPTURE_MAX_SIZE "file_capture_max"
55 #define FILE_SERVICE_OPT__CAPTURE_MIN_SIZE "file_capture_min"
56 #define FILE_SERVICE_OPT__CAPTURE_BLOCK_SIZE "file_capture_block_size"
57
58 #define FILE_SERVICE_TYPE_DEPTH_MIN 0
59 #define FILE_SERVICE_TYPE_DEPTH_MAX UINT32_MAX
60 #define FILE_SERVICE_SIG_DEPTH_MIN 0
61 #define FILE_SERVICE_SIG_DEPTH_MAX UINT32_MAX
62 #define FILE_SERVICE_BLOCK_TIMEOUT_MIN 0
63 #define FILE_SERVICE_BLOCK_TIMEOUT_MAX UINT32_MAX
64 #define FILE_SERVICE_LOOKUP_TIMEOUT_MIN 0
65 #define FILE_SERVICE_LOOKUP_TIMEOUT_MAX UINT32_MAX
66 #define FILE_SERVICE_CAPTURE_MEMCAP_MIN 1
67 #define FILE_SERVICE_CAPTURE_MEMCAP_MAX UINT32_MAX
68 #define FILE_SERVICE_CAPTURE_MAX_SIZE_MIN 0
69 #define FILE_SERVICE_CAPTURE_MAX_SIZE_MAX UINT32_MAX
70 #define FILE_SERVICE_CAPTURE_MIN_SIZE_MIN 0
71 #define FILE_SERVICE_CAPTURE_MIN_SIZE_MAX UINT32_MAX
72 #define FILE_SERVICE_CAPTURE_BLOCK_SIZE_MIN 8 /*at least 64bits*/
73 #define FILE_SERVICE_CAPTURE_BLOCK_SIZE_MAX UINT32_MAX
74
75 #define DEFAULT_FILE_TYPE_DEPTH 1460 // 1460 B
76 #define DEFAULT_FILE_SIGNATURE_DEPTH 10485760 // 10 MiB
77 #define DEFAULT_FILE_SHOW_DATA_DEPTH 100 // 100 B
78 #define DEFAULT_FILE_BLOCK_TIMEOUT 86400 // 1 day
79 #define DEFAULT_FILE_LOOKUP_TIMEOUT 2 // 2 seconds
80 #define DEFAULT_FILE_CAPTURE_MEM 100 // 100 MiB
81 #define DEFAULT_FILE_CAPTURE_MAX_SIZE 1048576 // 1 MiB
82 #define DEFAULT_FILE_CAPTURE_MIN_SIZE 0 // 0
83 #define DEFAULT_FILE_CAPTURE_BLOCK_SIZE 32768 // 32 KiB
84
85 #if defined(DEBUG_MSGS) || defined (REG_TEST)
86 #define FILE_SERVICE_OPT__TYPE "type_id"
87 #define FILE_SERVICE_OPT__SIG "signature"
88 #define FILE_SERVICE_OPT__SHOW_DATA_DEPTH "show_data_depth"
89 #include "file_api.h"
90 #endif
91
92 /*Set default values for file config*/
file_service_config_defaults(FileConfig * file_config)93 static inline void file_service_config_defaults(FileConfig *file_config)
94 {
95 file_config->file_type_depth = DEFAULT_FILE_TYPE_DEPTH;
96 file_config->file_signature_depth = DEFAULT_FILE_SIGNATURE_DEPTH;
97 file_config->file_block_timeout = DEFAULT_FILE_BLOCK_TIMEOUT;
98 file_config->file_lookup_timeout = DEFAULT_FILE_LOOKUP_TIMEOUT;
99 file_config->block_timeout_lookup = false;
100
101 #if defined(DEBUG_MSGS) || defined (REG_TEST)
102 file_config->show_data_depth = DEFAULT_FILE_SHOW_DATA_DEPTH;
103 #endif
104
105 file_config->file_capture_memcap = DEFAULT_FILE_CAPTURE_MEM;
106 file_config->file_capture_max_size = DEFAULT_FILE_CAPTURE_MAX_SIZE;
107 file_config->file_capture_min_size = DEFAULT_FILE_CAPTURE_MIN_SIZE;
108 file_config->file_capture_block_size = DEFAULT_FILE_CAPTURE_BLOCK_SIZE;
109 }
110
file_service_config_create(void)111 FileConfig* file_service_config_create(void)
112 {
113 FileConfig *file_config = SnortPreprocAlloc(1, sizeof(*file_config), PP_FILE, PP_MEM_CATEGORY_CONFIG);
114
115 file_service_config_defaults(file_config);
116 return file_config;
117 }
118
119 #if defined (SIDE_CHANNEL)
check_sidechannel_enabled(void * config)120 void check_sidechannel_enabled(void *config)
121 {
122 FileConfig *file_config = (FileConfig *)config;
123 if(ScSideChannelEnabled())
124 {
125 file_config->use_side_channel = true;
126
127 LogMessage("File service config: \n");
128
129 LogMessage(" File side channel enabled = %d \n",file_config->use_side_channel);
130 }
131 return;
132 }
133 #endif
134 #if defined (SIDE_CHANNEL) && defined (REG_TEST)
FileSSConfigFree(void * config)135 void FileSSConfigFree(void *config)
136 {
137 FileConfig *file_config = (FileConfig *)config;
138 FileSSConfig *file_ss_config = file_config->file_ss_config;
139 if (file_ss_config == NULL)
140 return;
141 /* Not changing the free here because memory is allocated using strdup */
142 if (file_ss_config->startup_input_file)
143 free(file_ss_config->startup_input_file);
144
145 /* Not changing the free here because memory is allocated using strdup */
146 if (file_ss_config->runtime_output_file)
147 free(file_ss_config->runtime_output_file);
148
149 SnortPreprocFree(file_ss_config, sizeof(FileSSConfig), PP_FILE, PP_MEM_CATEGORY_CONFIG);
150 return;
151 }
152 #endif
153
154 #ifdef SNORT_RELOAD
155 /* Verify the file service configuration, changing memory settings and depth
156 * settings requires snort restart
157 */
file_sevice_config_verify(SnortConfig * old,SnortConfig * new)158 int file_sevice_config_verify(SnortConfig *old, SnortConfig *new)
159 {
160 FileConfig *curr = (FileConfig *)old->file_config;
161 FileConfig *next = (FileConfig *)new->file_config;
162 FileConfig tmp;
163
164 /*no file config on both*/
165 if ((!curr) && (!next))
166 return 0;
167
168 /* use default value if nothing sets*/
169 if (!curr)
170 {
171 curr = &tmp;
172 file_service_config_defaults(curr);
173 }
174
175 if (!next)
176 {
177 next = &tmp;
178 file_service_config_defaults(next);
179 }
180 #if defined (SIDE_CHANNEL) && !defined (REG_TEST)
181 check_sidechannel_enabled(curr);
182 #endif
183
184 /* check configurations */
185 if (curr->file_capture_memcap != next->file_capture_memcap)
186 {
187 ErrorMessage("File service: Changing file capture memcap"
188 " requires a restart.\n");
189 return -1;
190 }
191
192 if (curr->file_capture_block_size != next->file_capture_block_size)
193 {
194 ErrorMessage("File service: Changing file capture block size"
195 " requires a restart.\n");
196 return -1;
197 }
198
199 return 0;
200 }
201 #endif
202
203 /* Display the configuration for the File preprocessor.
204 *
205 * PARAMETERS: None.
206 *
207 * RETURNS: Nothing.
208 */
file_service_display_conf(FileConfig * config)209 static void file_service_display_conf(FileConfig *config)
210 {
211
212 if (config == NULL)
213 return;
214
215 LogMessage("\n");
216
217 LogMessage("File service config: \n");
218
219 LogMessage(" File type depth: "STDi64" %s \n",
220 config->file_type_depth,
221 config->file_type_depth == DEFAULT_FILE_TYPE_DEPTH ?
222 "(Default) bytes" : " bytes" );
223
224 LogMessage(" File signature depth: "STDi64" %s \n",
225 config->file_signature_depth,
226 config->file_signature_depth == DEFAULT_FILE_SIGNATURE_DEPTH ?
227 "(Default) bytes" : " bytes" );
228
229 LogMessage(" File block timeout: "STDi64" %s \n",
230 config->file_block_timeout,
231 config->file_block_timeout == DEFAULT_FILE_BLOCK_TIMEOUT ?
232 "(Default) seconds" : " seconds" );
233
234 LogMessage(" File lookup timeout: "STDi64" %s \n",
235 config->file_lookup_timeout,
236 config->file_lookup_timeout == DEFAULT_FILE_LOOKUP_TIMEOUT ?
237 "(Default) seconds" : " seconds" );
238
239 LogMessage(" Action for lookup timeout: %s\n",
240 config->block_timeout_lookup ? "BLOCKED":"ALLOWED (Default)");
241
242 LogMessage(" File capture memcap: "STDi64" %s \n",
243 config->file_capture_memcap,
244 config->file_capture_memcap == DEFAULT_FILE_CAPTURE_MEM ?
245 "(Default) megabytes" : " megabytes" );
246
247 LogMessage(" File capture block size: "STDi64" %s \n",
248 config->file_capture_block_size,
249 config->file_capture_block_size == DEFAULT_FILE_CAPTURE_BLOCK_SIZE ?
250 "(Default) bytes" : " bytes" );
251
252 LogMessage(" File capture max size: "STDi64" %s \n",
253 config->file_capture_max_size,
254 config->file_capture_max_size == DEFAULT_FILE_CAPTURE_MAX_SIZE ?
255 "(Default) bytes" : " bytes" );
256
257 LogMessage(" File capture min size: "STDi64" %s \n",
258 config->file_capture_min_size,
259 config->file_capture_min_size == DEFAULT_FILE_CAPTURE_MIN_SIZE ?
260 "(Default) bytes" : " bytes" );
261 #if defined (SIDE_CHANNEL) && defined (REG_TEST)
262 FilePrintSSConfig(config->file_ss_config);
263 #endif
264
265 LogMessage("\n");
266 }
267 /*The main function for parsing rule option*/
file_service_config(struct _SnortConfig * sc,char * args,void * conf)268 void file_service_config(struct _SnortConfig* sc, char *args, void *conf)
269 {
270 char **toks;
271 int num_toks;
272 int i;
273 FileConfig *file_config = (FileConfig *)conf;
274 #if defined(DEBUG_MSGS) || defined (REG_TEST)
275 bool file_type_enabled = false;
276 bool file_signature_enabled = false;
277 #endif
278 DEBUG_WRAP(DebugMessage(DEBUG_FILE,"Loading file service configuration: %s\n", args););
279
280 if (!file_config)
281 {
282 return;
283 }
284
285 file_service_config_defaults(file_config);
286 #if defined (SIDE_CHANNEL) && defined (REG_TEST)
287 if (NULL == (file_config->file_ss_config = (FileSSConfig *)SnortPreprocAlloc(1,
288 sizeof(FileSSConfig), PP_FILE, PP_MEM_CATEGORY_CONFIG)))
289 return;
290 else if(ScSideChannelEnabled())
291 file_config->use_side_channel = true;
292 #endif
293
294 toks = mSplit(args, ",", 0, &num_toks, 0); /* get rule option pairs */
295
296 for (i = 0; i < num_toks; i++)
297 {
298 char **opts;
299 int num_opts;
300 char *option_args = NULL;
301 unsigned long value = 0;
302
303 DEBUG_WRAP(DebugMessage(DEBUG_FILE," option: %s\n", toks[i]););
304
305 /* break out the option name from its data */
306 opts = mSplit(toks[i], " ", 3, &num_opts, '\\');
307
308 DEBUG_WRAP(DebugMessage(DEBUG_FILE," option name: %s\n", opts[0]););
309
310 if (num_opts == 2)
311 {
312 option_args = opts[1];
313 DEBUG_WRAP(DebugMessage(DEBUG_FILE," option args: %s\n", option_args););
314 }
315 if ( !strcasecmp( opts[0], FILE_SERVICE_OPT__TYPE_DEPTH ))
316 {
317 CheckValueInRange(option_args, FILE_SERVICE_OPT__TYPE_DEPTH,
318 FILE_SERVICE_TYPE_DEPTH_MIN,
319 FILE_SERVICE_TYPE_DEPTH_MAX,
320 &value);
321 file_config->file_type_depth = (int64_t)value;
322 if (file_config->file_type_depth == 0)
323 file_config->file_type_depth = FILE_SERVICE_TYPE_DEPTH_MAX;
324 }
325 else if ( !strcasecmp( opts[0], FILE_SERVICE_OPT__SIG_DEPTH ))
326 {
327 CheckValueInRange(option_args, FILE_SERVICE_OPT__SIG_DEPTH,
328 FILE_SERVICE_SIG_DEPTH_MIN,
329 FILE_SERVICE_SIG_DEPTH_MAX,
330 &value);
331 file_config->file_signature_depth = (int64_t)value;
332 if (file_config->file_signature_depth == 0)
333 file_config->file_signature_depth = FILE_SERVICE_SIG_DEPTH_MAX;
334 }
335 else if ( !strcasecmp( opts[0], FILE_SERVICE_OPT__BLOCK_TIMEOUT ))
336 {
337 CheckValueInRange(option_args, FILE_SERVICE_OPT__BLOCK_TIMEOUT,
338 FILE_SERVICE_BLOCK_TIMEOUT_MIN,
339 FILE_SERVICE_BLOCK_TIMEOUT_MAX,
340 &value);
341 file_config->file_block_timeout = (int64_t)value;
342 if (file_config->file_block_timeout == 0)
343 file_config->file_block_timeout = FILE_SERVICE_BLOCK_TIMEOUT_MAX;
344 }
345 else if ( !strcasecmp( opts[0], FILE_SERVICE_OPT__LOOKUP_TIMEOUT ))
346 {
347 CheckValueInRange(option_args, FILE_SERVICE_OPT__LOOKUP_TIMEOUT,
348 FILE_SERVICE_LOOKUP_TIMEOUT_MIN,
349 FILE_SERVICE_LOOKUP_TIMEOUT_MAX,
350 &value);
351 file_config->file_lookup_timeout = (int64_t)value;
352 if (file_config->file_lookup_timeout == 0)
353 file_config->file_lookup_timeout = FILE_SERVICE_LOOKUP_TIMEOUT_MAX;
354 }
355 else if ( !strcasecmp( opts[0], FILE_SERVICE_OPT__BLOCK_TIMEOUT_LOOKUP ))
356 {
357 file_config->block_timeout_lookup = true;
358 }
359 else if ( !strcasecmp( opts[0], FILE_SERVICE_OPT__CAPTURE_MEMCAP ))
360 {
361 CheckValueInRange(option_args, FILE_SERVICE_OPT__CAPTURE_MEMCAP,
362 FILE_SERVICE_CAPTURE_MEMCAP_MIN, FILE_SERVICE_CAPTURE_MEMCAP_MAX,
363 &value);
364 file_config->file_capture_memcap = (int64_t) value;
365 }
366 else if ( !strcasecmp( opts[0], FILE_SERVICE_OPT__CAPTURE_MAX_SIZE ))
367 {
368 CheckValueInRange(option_args, FILE_SERVICE_OPT__CAPTURE_MAX_SIZE,
369 FILE_SERVICE_CAPTURE_MAX_SIZE_MIN,
370 FILE_SERVICE_CAPTURE_MAX_SIZE_MAX,
371 &value);
372 file_config->file_capture_max_size = (int64_t) value;
373 }
374 else if ( !strcasecmp( opts[0], FILE_SERVICE_OPT__CAPTURE_MIN_SIZE ))
375 {
376 CheckValueInRange(option_args, FILE_SERVICE_OPT__CAPTURE_MIN_SIZE,
377 FILE_SERVICE_CAPTURE_MIN_SIZE_MIN,
378 FILE_SERVICE_CAPTURE_MIN_SIZE_MAX,
379 &value);
380 file_config->file_capture_min_size = (int64_t)value;
381 }
382 else if ( !strcasecmp( opts[0], FILE_SERVICE_OPT__CAPTURE_BLOCK_SIZE ))
383 {
384 CheckValueInRange(option_args, FILE_SERVICE_OPT__CAPTURE_BLOCK_SIZE,
385 FILE_SERVICE_CAPTURE_BLOCK_SIZE_MIN,
386 FILE_SERVICE_CAPTURE_BLOCK_SIZE_MAX,
387 &value);
388 file_config->file_capture_block_size = (int64_t) value;
389 }
390 #if defined(DEBUG_MSGS) || defined (REG_TEST)
391 else if ( !strcasecmp( opts[0], FILE_SERVICE_OPT__TYPE ))
392 {
393 file_type_enabled = true;
394
395 }
396 else if ( !strcasecmp( opts[0], FILE_SERVICE_OPT__SIG ))
397 {
398 file_signature_enabled = true;
399 }
400 else if ( !strcasecmp( opts[0], FILE_SERVICE_OPT__SHOW_DATA_DEPTH ))
401 {
402 CheckValueInRange(option_args, FILE_SERVICE_OPT__SHOW_DATA_DEPTH,
403 FILE_SERVICE_SIG_DEPTH_MIN,
404 FILE_SERVICE_SIG_DEPTH_MAX,
405 &value);
406 file_config->show_data_depth = (int64_t)value;
407 if (file_config->show_data_depth == 0)
408 file_config->show_data_depth = FILE_SERVICE_SIG_DEPTH_MAX;
409 }
410 #endif
411 #if defined (SIDE_CHANNEL) && defined (REG_TEST)
412 else if(!strcasecmp(opts[0], "ss_startup_input_file"))
413 {
414 file_config->file_ss_config->startup_input_file = strdup(opts[1]);
415 }
416 else if(!strcasecmp(opts[0], "ss_runtime_output_file"))
417 {
418 file_config->file_ss_config->runtime_output_file = strdup(opts[1]);
419 }
420 #endif
421 else
422 {
423 ParseError("File service: Invalid argument: %s\n", opts[0]);
424 return;
425 }
426 mSplitFree(&opts, num_opts);
427 }
428
429 #if defined(DEBUG_MSGS) || defined (REG_TEST)
430 if (file_type_enabled)
431 file_api->enable_file_type(sc, NULL);
432 if (file_signature_enabled)
433 file_api->enable_file_signature(sc, NULL);
434 #endif
435 /* file capture memcap should not be larger file capture block size*/
436 if (file_config->file_capture_block_size >
437 (file_config->file_capture_memcap << 20))
438 {
439 ParseError("File service: file capture block size ("STDi64")"
440 " is larger than file capture memcap ("STDi64") bytes.",
441 file_config->file_capture_block_size,
442 file_config->file_capture_memcap << 20);
443 }
444
445 /* file capture size should not be larger file signature depth*/
446 if (file_config->file_capture_max_size > file_config->file_signature_depth)
447 {
448 ParseError("File service: file capture max size ("STDi64") "
449 "is larger than file signature depth ("STDi64").",
450 file_config->file_capture_max_size,
451 file_config->file_signature_depth);
452 }
453
454 /* file capture min size should not be larger file capture max size*/
455 if (file_config->file_capture_min_size > file_config->file_capture_max_size)
456 {
457 ParseError("File service: file capture min size ("STDi64") "
458 "is larger than file capture max size ("STDi64").",
459 file_config->file_capture_min_size,
460 file_config->file_capture_max_size);
461 }
462
463 file_service_display_conf(file_config);
464
465 mSplitFree(&toks, num_toks);
466 }
467
468