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