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.12 - Initial Source Code. Hui Cao
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include "sf_types.h"
32 #include <sys/types.h>
33 #include "file_api.h"
34 #include "file_config.h"
35 #include "file_mime_config.h"
36 #include "file_capture.h"
37 #include "file_stats.h"
38 
39 #include "session_api.h"
40 #include "stream_api.h"
41 #include "mstring.h"
42 #include "preprocids.h"
43 #include "detect.h"
44 #include "plugbase.h"
45 #include "active.h"
46 
47 #include "file_mime_process.h"
48 #include "file_resume_block.h"
49 #include "snort_httpinspect.h"
50 #include "file_service.h"
51 #include "file_segment_process.h"
52 
53 static bool file_type_force = false;
54 
55 static uint32_t file_config_version = 0;
56 
57 FileServiceConfig cur_config;
58 static FileServiceConfig new_config;
59 static FileServiceConfig init_config;
60 
61 /*Main File Processing functions */
62 static int file_process(void* ssnptr, uint8_t* file_data, int data_size,
63         FilePosition position, bool upload, bool suspend_block_verdict, bool do_flush);
64 
65 /*File properties*/
66 static int get_file_name(void* ssnptr, uint8_t **fname, uint32_t *name_size);
67 static uint64_t get_file_size(void* ssnptr);
68 static uint64_t get_file_processed_size(void* ssnptr);
69 static bool get_file_direction(void* ssnptr);
70 static uint8_t *get_file_sig_sha256(void* ssnptr);
71 
72 static void set_file_name(void* ssnptr, uint8_t * fname, uint32_t name_size,
73         bool save_in_context);
74 static void set_file_direction(void* ssnptr, bool upload);
75 
76 static void set_file_policy_callback(File_policy_callback_func);
77 static void enable_file_type(struct _SnortConfig* sc, File_type_callback_func);
78 static void enable_file_signature(struct _SnortConfig* sc, File_signature_callback_func);
79 static void enable_file_capture(struct _SnortConfig* sc, File_signature_callback_func );
80 static void set_file_action_log_callback(Log_file_action_func);
81 
82 static int64_t get_max_file_depth(struct _SnortConfig *snort_conf, bool next);
83 static bool is_file_signature_enabled(void);
84 
85 static uint32_t str_to_hash(uint8_t *str, int length );
86 
87 static void file_signature_lookup(void* p, bool is_retransmit);
88 static void file_signature_callback(Packet* p);
89 
90 static inline void finish_signature_lookup(FileContext *context);
91 static File_Verdict get_file_verdict(void *ssnptr);
92 static void render_block_verdict(void *ctx, void *p);
93 
94 static bool is_file_service_enabled(void);
95 static uint32_t get_file_type_id(void *ssnptr);
96 static uint32_t get_new_file_instance(void *ssnptr);
97 static void set_file_partial(void *p, FilePosition position, bool upload, bool is_partial);
98 
99 /* File context based file processing*/
100 FileContext* create_file_context(void *ssnptr);
101 static void init_file_context(void *ssnptr, bool upload, FileContext *context);
102 bool set_current_file_context(void *ssnptr, FileContext *ctx);
103 FileContext* get_current_file_context(void *ssnptr);
104 FileContext* get_main_file_context(void *ssnptr);
105 static int process_file_context(FileContext *ctx, void *p, uint8_t *file_data,
106         int data_size, FilePosition position, bool suspend_block_verdict);
107 static FilePosition get_file_position(void *pkt);
108 static bool check_paf_abort(void* ssn);
109 static int64_t get_max_file_capture_size(void *ssn);
110 static void file_session_free(void *session_data);
111 extern FileEntry *file_cache_get(FileCache *fileCache, void* p, uint64_t file_id,
112     bool can_create);
113 static FileCharEncoding get_character_encoding(uint8_t *buffer, uint32_t length);
114 void file_event_log_dump(FileCache *fileCache, void* p, uint64_t file_id);
115 static void file_signature_reset(void* ssnptr);
116 static char* file_get_filetype (void *ssnptr);
117 
118 FileAPI fileAPI;
119 FileAPI* file_api = NULL;
120 
121 static unsigned s_cb_id = 0;
122 static ThrottleInfo error_throttleInfo = {0,60,0};
123 
init_fileAPI(void)124 void init_fileAPI(void)
125 {
126     fileAPI.version = FILE_API_VERSION;
127     fileAPI.is_file_service_enabled = &is_file_service_enabled;
128     fileAPI.file_process = &file_process;
129     fileAPI.get_file_name = &get_file_name;
130     fileAPI.get_file_size = &get_file_size;
131     fileAPI.get_file_processed_size = &get_file_processed_size;
132     fileAPI.get_file_direction = &get_file_direction;
133     fileAPI.get_sig_sha256 = &get_file_sig_sha256;
134     fileAPI.set_file_name = &set_file_name;
135     fileAPI.set_file_direction = &set_file_direction;
136     fileAPI.set_file_policy_callback = &set_file_policy_callback;
137     fileAPI.enable_file_type = &enable_file_type;
138     fileAPI.enable_file_signature = &enable_file_signature;
139     fileAPI.enable_file_capture = &enable_file_capture;
140     fileAPI.set_file_action_log_callback = &set_file_action_log_callback;
141     fileAPI.install_file_service = &FileServiceInstall;
142     fileAPI.get_max_file_depth = &get_max_file_depth;
143     fileAPI.is_file_signature_enabled = &is_file_signature_enabled;
144     fileAPI.set_log_buffers = &set_log_buffers;
145 #ifdef SNORT_RELOAD
146     fileAPI.update_mime_mempool = &update_mime_mempool;
147     fileAPI.update_log_mempool = &update_log_mempool;
148 #ifdef REG_TEST
149     fileAPI.displayMimeMempool = &displayMimeMempool;
150     fileAPI.displayLogMempool = &displayLogMempool;
151     fileAPI.displayDecodeDepth = &displayDecodeDepth;
152 #endif
153 #endif
154     fileAPI.init_mime_mempool = &init_mime_mempool;
155     fileAPI.init_log_mempool=  &init_log_mempool;
156     fileAPI.file_resume_block_add_file = &file_resume_block_add_file;
157     fileAPI.file_resume_block_check = &file_resume_block_check;
158     fileAPI.str_to_hash = &str_to_hash;
159     fileAPI.file_signature_lookup = &file_signature_lookup;
160     fileAPI.set_mime_decode_config_defauts = &set_mime_decode_config_defauts;
161     fileAPI.set_mime_log_config_defauts = &set_mime_log_config_defauts;
162     fileAPI.parse_mime_decode_args = &parse_mime_decode_args;
163     fileAPI.process_mime_data = &process_mime_data;
164     fileAPI.free_mime_session = &free_mime_session;
165     fileAPI.is_decoding_enabled = &is_decoding_enabled;
166     fileAPI.check_decoding_conf = &check_decode_config;
167     fileAPI.is_mime_log_enabled = &is_mime_log_enabled;
168     fileAPI.finalize_mime_position = &finalize_mime_position;
169     fileAPI.get_file_verdict = &get_file_verdict;
170     fileAPI.render_block_verdict = &render_block_verdict;
171     fileAPI.reserve_file = &file_capture_reserve;
172     fileAPI.read_file = &file_capture_read;
173     fileAPI.release_file = &file_capture_release;
174     fileAPI.get_file_capture_size = &file_capture_size;
175     fileAPI.get_file_type_id = &get_file_type_id;
176     fileAPI.get_new_file_instance = &get_new_file_instance;
177 
178     fileAPI.create_file_context = &create_file_context;
179     fileAPI.init_file_context = &init_file_context;
180     fileAPI.set_current_file_context = &set_current_file_context;
181     fileAPI.get_current_file_context = &get_current_file_context;
182     fileAPI.get_main_file_context = &get_main_file_context;
183     fileAPI.process_file = &process_file_context;
184     fileAPI.get_file_position = &get_file_position;
185     fileAPI.reset_mime_paf_state = &reset_mime_paf_state;
186     fileAPI.process_mime_paf_data = &process_mime_paf_data;
187     fileAPI.check_data_end = check_data_end;
188     fileAPI.check_paf_abort = &check_paf_abort;
189     fileAPI.get_max_file_capture_size = get_max_file_capture_size;
190     fileAPI.file_cache_update_entry = &file_cache_update_entry;
191     fileAPI.file_segment_process = &file_segment_process;
192     fileAPI.file_cache_create = &file_cache_create;
193     fileAPI.file_cache_free = &file_cache_free;
194     fileAPI.file_cache_status = &file_cache_status;
195     fileAPI.file_config_malware_check = &file_config_malware_check;
196     fileAPI.get_character_encoding = &get_character_encoding;
197     fileAPI.file_cache_shrink_to_memcap = &file_cache_shrink_to_memcap;
198     fileAPI.file_cache_set_memcap = &file_cache_set_memcap;
199     fileAPI.file_event_log_dump = &file_event_log_dump;
200     fileAPI.file_signature_reset= &file_signature_reset;
201     fileAPI.set_file_partial = &set_file_partial;
202     fileAPI.file_get_filetype = &file_get_filetype;
203     file_api = &fileAPI;
204     init_mime();
205     RegisterMemoryStatsFunction(PP_FILE, FilePrintMemStats);
206 }
207 
208 
209 #if defined(DEBUG_MSGS) || defined (REG_TEST)
printFileServiceChanges()210 static void printFileServiceChanges()
211 {
212    FileConfig *file_config =  (FileConfig *)(snort_conf->file_config);
213    if(cur_config.file_signature_enabled != new_config.file_signature_enabled)
214        printf("File service Install: file_signature %s\n",new_config.file_signature_enabled ? "enabled":"disabled");
215    if(cur_config.file_type_id_enabled != new_config.file_type_id_enabled)
216        printf("File service Install: file_type %s\n",new_config.file_type_id_enabled ? "enabled":"disabled");
217    if(cur_config.file_capture_enabled != new_config.file_capture_enabled)
218        printf("File service Install: file_capture %s\n",new_config.file_capture_enabled ? "enabled":"disabled");
219 
220    if (!file_config)
221        return;
222    if(new_config.file_type_id_enabled)
223        printf("File service Install: file_type_depth:%u \n",(unsigned)file_config->file_type_depth);
224    if(new_config.file_signature_enabled)
225        printf("File service Install: file_signature_depth:%u \n",(unsigned)file_config->file_signature_depth);
226    fflush(stdout);
227 }
228 #endif
229 
FileServiceInstall(void)230 void FileServiceInstall(void)
231 {
232 #if defined(DEBUG_MSGS) || defined (REG_TEST)
233     printFileServiceChanges();
234 #endif
235     cur_config = new_config;
236     new_config = init_config;
237 
238     if (stream_api)
239     {
240         if(cur_config.file_signature_enabled &&
241                 !s_cb_id )
242             s_cb_id = stream_api->register_event_handler(file_signature_callback);
243     }
244 }
245 
start_file_processing(struct _SnortConfig * sc,bool capture)246 static void start_file_processing(struct _SnortConfig* sc, bool capture)
247 {
248     static bool file_processing_initiated = false;
249 
250     if (!file_processing_initiated)
251     {
252         file_resume_block_init();
253         RegisterPreprocStats("file", print_file_stats);
254         file_processing_initiated = true;
255     }
256 
257     if (!sc)
258         sc = snort_conf;
259 
260     if (!sc->file_config)
261         sc->file_config = file_service_config_create();
262 
263     if (capture)
264     {
265         FileConfig* file_config = sc->file_config;
266         file_capture_init_mempool(file_config->file_capture_memcap,
267                 file_config->file_capture_block_size);
268     }
269 }
270 
free_file_config(void * conf)271 void free_file_config(void *conf)
272 {
273     file_config_version++;
274     file_rule_free(conf);
275     file_identifiers_free(conf);
276     SnortPreprocFree(conf, sizeof(FileConfig), PP_FILE, PP_MEM_CATEGORY_CONFIG);
277 }
278 
close_fileAPI(void)279 void close_fileAPI(void)
280 {
281     file_resume_block_cleanup();
282     free_mime();
283     file_caputure_close();
284 }
285 
get_file_session(void * ssnptr)286 FileSession* get_file_session(void *ssnptr)
287 {
288     return ((FileSession*)session_api->get_application_data(ssnptr, PP_FILE));
289 }
290 
get_create_file_session(void * ssnptr)291 static inline FileSession* get_create_file_session(void *ssnptr)
292 {
293     FileSession *file_session = get_file_session(ssnptr);
294     if(!file_session)
295     {
296         file_session = (FileSession *)SnortPreprocAlloc(1, sizeof(*file_session),
297                 PP_FILE, PP_MEM_CATEGORY_SESSION);
298         if (session_api->set_application_data(ssnptr, PP_FILE, file_session,
299                 file_session_free))
300         {
301             SnortPreprocFree(file_session, sizeof(*file_session),
302                     PP_FILE, PP_MEM_CATEGORY_SESSION);
303             return NULL;
304         }
305     }
306     return(file_session);
307 }
308 
309 /*Get the current working file context*/
get_current_file_context(void * ssnptr)310 FileContext* get_current_file_context(void *ssnptr)
311 {
312     FileSession *file_session = get_file_session (ssnptr);
313     if (file_session)
314         return file_session->current_context;
315     else
316     {
317         FILE_WARNING("Failed to get current file context: file session not found");
318         return NULL;
319     }
320 }
321 
322 /*Get the current main file context*/
get_main_file_context(void * ssnptr)323 FileContext* get_main_file_context(void *ssnptr)
324 {
325     FileSession *file_session = get_file_session (ssnptr);
326     if (file_session)
327         return file_session->main_context;
328     else
329     {
330         FILE_WARNING("Failed to get main file context: file session not found");
331         return NULL;
332     }
333 }
334 
335 /*Get the current working file context*/
save_to_pending_context(void * ssnptr)336 static inline void save_to_pending_context(void *ssnptr)
337 {
338     FileSession *file_session = get_create_file_session (ssnptr);
339     /* Save to pending_context */
340     if (!file_session)
341         return;
342 
343     if (file_session->main_context)
344     {
345         if (file_session->pending_context != file_session->main_context)
346             file_context_free(file_session->pending_context);
347         file_session->pending_context = file_session->main_context;
348     }
349     else
350     {
351         file_session->pending_context = file_session->current_context;
352     }
353 }
354 
355 /*Set the current working file context*/
set_current_file_context(void * ssnptr,FileContext * ctx)356 bool set_current_file_context(void *ssnptr, FileContext *ctx)
357 {
358     FileSession *file_session = get_create_file_session (ssnptr);
359 
360     if (!file_session)
361     {
362         FILE_WARNING("Failed to set current file context: file session not found");
363         return false;
364     }
365 
366     file_session->current_context = ctx;
367     return true;
368 }
369 
file_session_free(void * session_data)370 static void file_session_free(void *session_data)
371 {
372     FileSession *file_session = (FileSession *)session_data;
373     if (!file_session)
374         return;
375 
376     /*Clean up all the file contexts*/
377     if (file_session->main_context)
378     {
379         if ( file_session->pending_context &&
380                 (file_session->main_context != file_session->pending_context))
381         {
382             file_context_free(file_session->pending_context);
383         }
384 
385         file_context_free(file_session->main_context);
386     }
387     SnortPreprocFree(file_session, sizeof(FileSession), PP_FILE,
388              PP_MEM_CATEGORY_SESSION);
389 }
390 
init_file_context(void * ssnptr,bool upload,FileContext * context)391 static void init_file_context(void *ssnptr, bool upload, FileContext *context)
392 {
393     context->file_type_enabled = cur_config.file_type_id_enabled;
394     context->file_signature_enabled = cur_config.file_signature_enabled;
395     context->file_capture_enabled = cur_config.file_capture_enabled;
396     context->file_config = snort_conf->file_config;
397     context->file_config_version = file_config_version;
398     context->smb_unknown_file_size = false;
399     context->partial_file = false;
400     context->attached_file_entry = NULL;
401     file_direction_set(context,upload);
402     file_stats.files_total++;
403 #ifdef TARGET_BASED
404     /* Check file policy to see whether we want to do either file type, file
405      * signature,  or file capture
406      * Note: this happen only on the start of session*/
407     if (cur_config.file_policy_cb)
408     {
409         uint32_t policy_flags = 0;
410         context->app_id = session_api->get_application_protocol_id(ssnptr);
411 
412         policy_flags = cur_config.file_policy_cb(ssnptr, context->app_id, upload);
413 
414         if ( !file_type_force && !(policy_flags & ENABLE_FILE_TYPE_IDENTIFICATION) )
415                 context->file_type_enabled = false;
416 
417         if ( !(policy_flags & ENABLE_FILE_SIGNATURE_SHA256) )
418             context->file_signature_enabled = false;
419 
420         if ( !(policy_flags & ENABLE_FILE_CAPTURE) )
421             context->file_capture_enabled = false;
422     }
423 #endif
424 }
425 
create_file_context(void * ssnptr)426 FileContext* create_file_context(void *ssnptr)
427 {
428     FileContext *context = file_context_create();
429 
430     /* Create file session if not yet*/
431     get_create_file_session (ssnptr);
432     FILE_DEBUG("Successfully created file context %p",context);
433 
434     return context;
435 }
436 
find_main_file_context(void * p,FilePosition position,bool upload)437 static inline FileContext* find_main_file_context(void* p, FilePosition position,
438         bool upload)
439 {
440     FileContext* context = NULL;
441     Packet *pkt = (Packet *)p;
442     void *ssnptr = pkt->ssnptr;
443     FileSession *file_session = get_file_session (ssnptr);
444 
445     /* Attempt to get a previously allocated context. */
446     if (file_session)
447         context  = file_session->main_context;
448 
449     if (context && (((position == SNORT_FILE_MIDDLE) || (position == SNORT_FILE_END)) ||
450                 ((context->partial_file) && (SNORT_FILE_START == position))))
451         return context;
452     else if (context)
453     {
454         /*Push file event when there is another file in the same packet*/
455         if (pkt->packet_flags & PKT_FILE_EVENT_SET)
456         {
457             SnortEventqLog(snort_conf->event_queue, p);
458             SnortEventqReset();
459             pkt->packet_flags &= ~PKT_FILE_EVENT_SET;
460         }
461 
462         if (context->verdict != FILE_VERDICT_PENDING)
463         {
464             /* Reuse the same context */
465             file_context_reset(context);
466             init_file_context(ssnptr, upload, context);
467             context->file_id = file_session->max_file_id++;
468             FILE_DEBUG("Reusing existing context from last session");
469             return context;
470         }
471     }
472 
473     context = create_file_context(ssnptr);
474     file_session = get_create_file_session (ssnptr);
475     file_session->main_context = context;
476     init_file_context(ssnptr, upload, context);
477     context->file_id = file_session->max_file_id++;
478     return context;
479 }
480 
updateFileSize(FileContext * context,int data_size,FilePosition position)481 static inline void updateFileSize(FileContext* context, int data_size,
482         FilePosition position)
483 {
484     context->processed_bytes += data_size;
485     if ((position == SNORT_FILE_END) || (position == SNORT_FILE_FULL) || (context->file_state.sig_state == FILE_SIG_FLUSH))
486     {
487         if (get_max_file_depth(snort_conf, false) == (int64_t)context->processed_bytes)
488             context->file_size = 0;
489         else
490             context->file_size = context->processed_bytes;
491     }
492     FILE_DEBUG("Processed bytes: %u, Updated file size is: %u " ,context->processed_bytes, context->file_size);
493     if((SNORT_FILE_FULL == position) || (SNORT_FILE_END == position))
494     {
495         context->processed_bytes = 0;
496     }
497 }
498 
file_eventq_add(uint32_t gid,uint32_t sid,char * msg,RuleType type)499 int file_eventq_add(uint32_t gid, uint32_t sid, char *msg, RuleType type)
500 {
501     OptTreeNode *otn;
502     RuleTreeNode *rtn;
503 
504     otn = GetApplicableOtn(gid, sid, 1, 0, 3, msg);
505     if (otn == NULL)
506     {
507         FILE_ERROR("Failed to add event: no otn");
508         return 0;
509 
510     }
511     rtn = getRtnFromOtn(otn, getIpsRuntimePolicy());
512     if (rtn == NULL)
513     {
514         FILE_ERROR("Failed to add event: no rtn");
515         return 0;
516     }
517 
518     rtn->type = type;
519 
520     return SnortEventqAdd(gid, sid, 1, 0, 3, msg, otn);
521 }
522 
523 
add_file_to_block(Packet * p,FileContext * context,bool signature_available)524 static inline void add_file_to_block(Packet *p, FileContext* context,
525         bool signature_available)
526 {
527     uint8_t *buf = NULL;
528     uint32_t len = 0;
529     uint32_t type = 0;
530     uint32_t file_sig = 0;
531     uint8_t* signature = signature_available ? context->sha256 : NULL;
532     Packet *pkt = (Packet *)p;
533     FileConfig *file_config =  (FileConfig *)(snort_conf->file_config);
534 
535     Active_ForceDropPacket();
536     DisableAllDetect( p );
537     pkt->packet_flags |= PKT_FILE_EVENT_SET;
538 
539     /*Use URI as the identifier for file*/
540     if (GetHttpUriData(p->ssnptr, &buf, &len, &type))
541     {
542         file_sig = str_to_hash(buf, len);
543         file_resume_block_add_file(p, file_sig,
544                 (uint32_t)file_config->file_block_timeout, context->verdict,
545                 context->file_type_id, signature, 0, 0, true, 0);
546     }
547     /*use the file name for smb2*/
548     else if(context->attached_file_entry && context->file_name_size > 0)
549     {
550         file_sig = str_to_hash(context->file_name, context->file_name_size);
551         file_resume_block_add_file(p, file_sig,
552                 (uint32_t)file_config->file_block_timeout, context->verdict,
553                 context->file_type_id, signature, 0, 0, true, 0);
554         /*We cant call file_entry_free directly as that will delete the context, but we still may be using it.
555           So we are unlinking the context from the file entry. this way the context will not be deleted now,
556           but it will be deleted as part of tcp cleanup. As no context is linked to the file entry now, it will
557           be set to do resume check. */
558         ((FileEntry*)(context->attached_file_entry))->context = NULL;
559         context->attached_file_entry = NULL;
560     }
561 
562     FILE_INFO("File blocked");
563     if (pkt_trace_enabled)
564         addPktTraceData(VERDICT_REASON_FILE, snprintf(trace_line, MAX_TRACE_LINE,
565             "File Process: %s %s\n", getPktTraceActMsg(), (buf && len)? (char *)buf : ""));
566     else addPktTraceData(VERDICT_REASON_FILE, 0);
567 }
568 /*
569  * Check HTTP partial content header
570  * Return: 1: partial content header
571  *         0: not http partial content header
572  */
check_http_partial_content(Packet * p)573 static inline int check_http_partial_content(Packet *p)
574 {
575     uint8_t *buf = NULL;
576     uint32_t len = 0;
577     uint32_t type = 0;
578     uint32_t file_sig;
579     const HttpBuffer* hb = GetHttpBuffer(HTTP_BUFFER_STAT_CODE);
580     uint8_t partial_cont = isHttpRespPartialCont(p->ssnptr);
581     int is_not_partial_ret_code = 0;
582 
583     /* Not partial content, return */
584     if (hb)
585     {
586         if (hb->length != 3)
587         {
588             is_not_partial_ret_code = 1;
589         }
590         else
591         {
592             is_not_partial_ret_code = strncmp((const char*)hb->buf, "206", 3);
593         }
594         if (((is_not_partial_ret_code) && !(partial_cont &= PARTIAL_CONTENT)) ||
595             ((!is_not_partial_ret_code) && (partial_cont &= FULL_CONTENT)))
596         {
597             return 0;
598         }
599     }
600     else if (!(partial_cont &= PARTIAL_CONTENT))
601     {
602         return 0;
603     }
604 
605     /*Use URI as the identifier for file*/
606     if (GetHttpUriData(p->ssnptr, &buf, &len, &type))
607     {
608         file_sig = str_to_hash(buf, len);
609         file_resume_block_check(p, file_sig);
610     }
611     FILE_DEBUG("HTTP partial content header found");
612 
613     return 1;
614 }
615 
616 /* File signature lookup at the end of file
617  * File signature callback can be used for malware lookup, file capture etc
618  */
_file_signature_lookup(FileContext * context,void * p,bool is_retransmit,bool suspend_block_verdict)619 static inline void _file_signature_lookup(FileContext* context,
620         void* p, bool is_retransmit, bool suspend_block_verdict)
621 {
622     File_Verdict verdict = FILE_VERDICT_UNKNOWN;
623     Packet *pkt = (Packet *)p;
624     void *ssnptr = pkt->ssnptr;
625 
626     if (cur_config.file_signature_cb)
627     {
628         FILE_DEBUG("Doing file signature callback...");
629         verdict = cur_config.file_signature_cb(p, ssnptr, context->sha256,
630                 context->file_size, &(context->file_state), context->upload,
631                 context->file_id, context->partial_file);
632         if(context->file_state.sig_state != FILE_SIG_FLUSH)
633             file_stats.verdicts_signature[verdict]++;
634     }
635     FILE_INFO("File Signature lookup verdict: %d", verdict);
636 
637     if (suspend_block_verdict)
638         context->suspend_block_verdict = true;
639 
640     context->verdict = verdict;
641 
642     if ((verdict == FILE_VERDICT_LOG ) && (context->file_state.sig_state != FILE_SIG_FLUSH))
643     {
644         file_eventq_add(GENERATOR_FILE_SIGNATURE, FILE_SIGNATURE_SHA256,
645                 FILE_SIGNATURE_SHA256_STR, RULE_TYPE__ALERT);
646         pkt->packet_flags |= PKT_FILE_EVENT_SET;
647         context->file_signature_enabled = false;
648     }
649     else if (verdict == FILE_VERDICT_PENDING)
650     {
651         /*Can't decide verdict, drop packet and waiting...*/
652         if (is_retransmit)
653         {
654             FileConfig *file_config =  (FileConfig *)context->file_config;
655             /*Drop packets if not timeout*/
656             if (pkt->pkth->ts.tv_sec <= context->expires)
657             {
658                 if( !Active_DAQRetryPacket(pkt) )
659                     Active_ForceDropPacket();
660                 if (pkt_trace_enabled)
661                 {
662                     addPktTraceData(VERDICT_REASON_FILE, snprintf(trace_line, MAX_TRACE_LINE,
663                         "File Process: malware detected, gid %u, sid %u, %s\n",
664                         GENERATOR_FILE_SIGNATURE, FILE_SIGNATURE_SHA256, getPktTraceActMsg()));
665                 }
666                 else addPktTraceData(VERDICT_REASON_FILE, 0);
667                 FILE_INFO("Malware detected");
668                 return;
669             }
670             /*Timeout, let packet go through OR block based on config*/
671             context->file_signature_enabled = false;
672             if (pkt_trace_enabled)
673             {
674                 addPktTraceData(VERDICT_REASON_FILE, snprintf(trace_line, MAX_TRACE_LINE,
675                             "File Process: file signature lookup verdict pending timeout, %s\n", getPktTraceActMsg()));
676             }
677             else addPktTraceData(VERDICT_REASON_FILE, 0);
678 
679             if (file_config && file_config->block_timeout_lookup)
680                 file_eventq_add(GENERATOR_FILE_SIGNATURE, FILE_SIGNATURE_SHA256,
681                         FILE_SIGNATURE_SHA256_STR, RULE_TYPE__REJECT);
682             else
683                 file_eventq_add(GENERATOR_FILE_SIGNATURE, FILE_SIGNATURE_SHA256,
684                         FILE_SIGNATURE_SHA256_STR, RULE_TYPE__ALERT);
685             pkt->packet_flags |= PKT_FILE_EVENT_SET;
686         }
687         else
688         {
689             FileConfig *file_config =  (FileConfig *)context->file_config;
690             if (file_config)
691                 context->expires = (time_t)(file_config->file_lookup_timeout + pkt->pkth->ts.tv_sec);
692 
693             if( !Active_DAQRetryPacket(pkt) )
694                 Active_ForceDropPacket();
695             if (pkt_trace_enabled)
696             {
697                 addPktTraceData(VERDICT_REASON_FILE, snprintf(trace_line, MAX_TRACE_LINE,
698                     "File Process: can't decide verdict and waiting, %s\n", getPktTraceActMsg()));
699             }
700             else addPktTraceData(VERDICT_REASON_FILE, 0);
701             if (!context->suspend_block_verdict)
702                 stream_api->set_event_handler(ssnptr, s_cb_id, SE_REXMIT);
703 
704             save_to_pending_context(ssnptr);
705             return;
706         }
707     }
708     else if ((verdict == FILE_VERDICT_BLOCK) || (verdict == FILE_VERDICT_REJECT))
709     {
710         if (!context->suspend_block_verdict)
711             render_block_verdict(context, p);
712         context->file_signature_enabled = false;
713         return;
714     }
715 
716     if(context->file_state.sig_state != FILE_SIG_FLUSH)
717         finish_signature_lookup(context);
718 }
719 
finish_signature_lookup(FileContext * context)720 static inline void finish_signature_lookup(FileContext *context)
721 {
722     if (context->sha256)
723     {
724         context->file_signature_enabled = false;
725         file_capture_stop(context);
726         file_stats.signatures_processed[context->file_type_id][context->upload]++;
727 #ifdef TARGET_BASED
728         file_stats.signatures_by_proto[context->app_id]++;
729 #endif
730     }
731 }
732 
get_file_verdict(void * ssnptr)733 static File_Verdict get_file_verdict(void *ssnptr)
734 {
735     FileContext *context = get_current_file_context(ssnptr);
736 
737     if (context == NULL)
738         return FILE_VERDICT_UNKNOWN;
739 
740     return context->verdict;
741 }
742 
render_block_verdict(void * ctx,void * p)743 static void render_block_verdict(void *ctx, void *p)
744 {
745     FileContext *context = (FileContext *)ctx;
746     Packet *pkt = (Packet *)p;
747     SAVE_DAQ_PKT_HDR(p);
748 
749     if (p == NULL)
750         return;
751 
752     if (context == NULL)
753     {
754         context = get_current_file_context(pkt->ssnptr);
755         if (context == NULL)
756             return;
757     }
758 
759     if (context->verdict == FILE_VERDICT_BLOCK)
760     {
761         file_eventq_add(GENERATOR_FILE_SIGNATURE, FILE_SIGNATURE_SHA256,
762                 FILE_SIGNATURE_SHA256_STR, RULE_TYPE__DROP);
763         add_file_to_block(p, context, true);
764     }
765     else if (context->verdict == FILE_VERDICT_REJECT)
766     {
767         file_eventq_add(GENERATOR_FILE_SIGNATURE, FILE_SIGNATURE_SHA256,
768                 FILE_SIGNATURE_SHA256_STR, RULE_TYPE__REJECT);
769         add_file_to_block(p, context, true);
770     }
771 
772     finish_signature_lookup(context);
773 }
774 
get_file_type_id(void * ssnptr)775 static uint32_t get_file_type_id(void *ssnptr)
776 {
777     // NOTE: 'ssnptr' NULL checked in get_application_data
778     FileContext *context = get_current_file_context(ssnptr);
779 
780     if ( !context )
781         return FILE_VERDICT_UNKNOWN;
782 
783     return context->file_type_id;
784 }
785 
get_new_file_instance(void * ssnptr)786 static uint32_t get_new_file_instance(void *ssnptr)
787 {
788     FileSession *file_session = get_create_file_session (ssnptr);
789 
790     if (file_session)
791     {
792         return file_session->max_file_id++;
793     }
794     else
795     {
796         return 0;
797     }
798 }
799 
file_signature_lookup(void * p,bool is_retransmit)800 static void file_signature_lookup(void* p, bool is_retransmit)
801 {
802     Packet *pkt = (Packet *)p;
803     SAVE_DAQ_PKT_HDR(p);
804 
805     FileContext* context  = get_current_file_context(pkt->ssnptr);
806 
807     if (context && context->file_signature_enabled && context->sha256)
808     {
809         _file_signature_lookup(context, p, is_retransmit, false);
810     }
811 }
812 
file_signature_callback(Packet * p)813 static void file_signature_callback(Packet* p)
814 {
815     /* During retransmission */
816     Packet *pkt = (Packet *)p;
817     void *ssnptr = pkt->ssnptr;
818     FileSession *file_session;
819     FileEntry *fileEntry;
820     SAVE_DAQ_PKT_HDR(p);
821 
822     if (!ssnptr)
823     {
824         FILE_ERROR("Signature callback failed: no session");
825         return;
826     }
827     file_session = get_file_session (ssnptr);
828     if (!file_session)
829     {
830         FILE_ERROR("Signature callback failed: no file session");
831         return;
832     }
833 
834     if(file_session->file_cache)
835     {
836         fileEntry = file_cache_get(file_session->file_cache, p, file_session->file_id, false);
837         if (fileEntry && fileEntry->context &&
838             (fileEntry->context->verdict == FILE_VERDICT_PENDING))
839         {
840             file_session->current_context = fileEntry->context;
841             file_signature_lookup(p, 1);
842         }
843     }
844     else
845     {
846         if(file_session->pending_context)
847         {
848             file_session->current_context = file_session->pending_context;
849         }
850         file_signature_lookup(p, 1);
851     }
852 }
853 
is_file_service_enabled()854 static bool is_file_service_enabled()
855 {
856     return (cur_config.file_type_id_enabled ||
857             cur_config.file_signature_enabled);
858 }
859 
860 /*
861  * Return:
862  *    1: continue processing/log/block this file
863  *    0: ignore this file
864  */
process_file_context(FileContext * context,void * p,uint8_t * file_data,int data_size,FilePosition position,bool suspend_block_verdict)865 static int process_file_context(FileContext *context, void *p, uint8_t *file_data,
866         int data_size, FilePosition position, bool suspend_block_verdict)
867 {
868     Packet *pkt = (Packet *)p;
869     void *ssnptr = pkt->ssnptr;
870     bool file_capture_enabled = false;
871     SAVE_DAQ_PKT_HDR(p);
872 
873     if (!context)
874         return 0;
875 
876     file_capture_enabled = context->file_capture_enabled;
877     set_current_file_context(ssnptr, context);
878     file_stats.file_data_total += data_size;
879 
880     /* if file config is changed, update it*/
881     if ((context->file_config != snort_conf->file_config) ||
882             (context->file_config_version != file_config_version))
883     {
884         context->file_config = snort_conf->file_config;
885         context->file_config_version = file_config_version;
886         /* Reset file type context that relies on file_conf.
887          * File type id will become UNKNOWN after file_type_id()
888          * if in the middle of file and file type is CONTINUE (undecided) */
889         context->file_type_context = NULL;
890         FILE_DEBUG("Updated file config.");
891     }
892 
893     if ((!context->file_type_enabled) && (!context->file_signature_enabled))
894     {
895         updateFileSize(context, data_size, position);
896         FILE_DEBUG("Signature and Type lookup not enabled");
897         return 0;
898     }
899 
900     if(check_http_partial_content(p))
901     {
902         context->file_type_enabled = false;
903         context->file_signature_enabled = false;
904         return 0;
905     }
906 
907     /*file type id*/
908     if (context->file_type_enabled)
909     {
910         File_Verdict verdict = FILE_VERDICT_UNKNOWN;
911 
912         file_type_id(context, file_data, data_size, position);
913         FILE_DEBUG("File type ID: %u", context->file_type_id);
914 
915         /*Don't care unknown file type*/
916         if (context->file_type_id == SNORT_FILE_TYPE_UNKNOWN)
917         {
918             context->file_type_enabled = false;
919             context->file_signature_enabled = false;
920             updateFileSize(context, data_size, position);
921             file_capture_stop(context);
922             return 0;
923         }
924 
925         if (context->file_type_id != SNORT_FILE_TYPE_CONTINUE)
926         {
927             if (cur_config.file_type_cb)
928             {
929                 FILE_DEBUG("Doing file type callback...");
930                 verdict = cur_config.file_type_cb(p, ssnptr, context->file_type_id,
931                         context->upload, context->file_id);
932                 FILE_INFO("File type verdict: %d",verdict);
933                 file_stats.verdicts_type[verdict]++;
934                 context->verdict = verdict;
935             }
936             context->file_type_enabled = false;
937             file_stats.files_processed[context->file_type_id][context->upload]++;
938 #ifdef TARGET_BASED
939             file_stats.files_by_proto[context->app_id]++;
940 #endif
941         }
942 
943         if (verdict == FILE_VERDICT_LOG )
944         {
945             file_eventq_add(GENERATOR_FILE_TYPE, context->file_type_id,
946                     file_type_name(context->file_config, context->file_type_id),
947                     RULE_TYPE__ALERT);
948             context->file_signature_enabled = false;
949             pkt->packet_flags |= PKT_FILE_EVENT_SET;
950         }
951         else if (verdict == FILE_VERDICT_BLOCK)
952         {
953             file_eventq_add(GENERATOR_FILE_TYPE, context->file_type_id,
954                     file_type_name(context->file_config, context->file_type_id),
955                     RULE_TYPE__DROP);
956             updateFileSize(context, data_size, position);
957             context->file_signature_enabled = false;
958             add_file_to_block(p, context, false);
959             return 1;
960         }
961         else if (verdict == FILE_VERDICT_REJECT)
962         {
963             file_eventq_add(GENERATOR_FILE_TYPE, context->file_type_id,
964                     file_type_name(context->file_config, context->file_type_id),
965                     RULE_TYPE__REJECT);
966             updateFileSize(context, data_size, position);
967             context->file_signature_enabled = false;
968             add_file_to_block(p, context, false);
969             return 1;
970         }
971         else if (verdict == FILE_VERDICT_STOP)
972         {
973             context->file_signature_enabled = false;
974         }
975         else if (verdict == FILE_VERDICT_STOP_CAPTURE)
976         {
977             file_capture_stop(context);
978         }
979     }
980 
981     /* file signature calculation */
982     if (context->file_signature_enabled)
983     {
984         if (!context->sha256)
985             file_signature_sha256(context, file_data, data_size, position);
986         file_stats.data_processed[context->file_type_id][context->upload]
987                                                          += data_size;
988         updateFileSize(context, data_size, position);
989 
990         /*Fails to capture, when out of memory or size limit, need lookup*/
991         if (context->file_capture_enabled &&
992                 file_capture_process(context, file_data, data_size, position))
993         {
994             file_capture_stop(context);
995             _file_signature_lookup(context, p, false, suspend_block_verdict);
996             if (context->verdict != FILE_VERDICT_UNKNOWN)
997                 return 1;
998         }
999 
1000         /*Either get SHA or exceeding the SHA limit, need lookup*/
1001 
1002         if (context->file_state.sig_state == FILE_SIG_DEPTH_FAIL)
1003         {
1004             file_stats.files_sig_depth++;
1005             _file_signature_lookup(context, p, false, suspend_block_verdict);
1006         }
1007         else if ((context->file_state.sig_state == FILE_SIG_DONE) && isFileEnd(position))
1008         {
1009             FILE_REG_DEBUG_WRAP(if (context->sha256) file_sha256_print(context->sha256);)
1010             _file_signature_lookup(context, p, false, suspend_block_verdict);
1011         }
1012         else if(context->file_state.sig_state == FILE_SIG_FLUSH)
1013         {
1014             _file_signature_lookup(context, p, false, suspend_block_verdict);
1015             context->file_signature_enabled = true;
1016             context->file_capture_enabled = file_capture_enabled;
1017             if((context->verdict == FILE_VERDICT_BLOCK) || (context->verdict == FILE_VERDICT_REJECT))
1018             {
1019                 FILE_REG_DEBUG_WRAP(if (context->sha256) file_sha256_print(context->sha256);)
1020             }
1021         }
1022     }
1023     else
1024     {
1025         updateFileSize(context, data_size, position);
1026     }
1027     return 1;
1028 }
1029 
1030 /*
1031  * Return:
1032  *    1: continue processing/log/block this file
1033  *    0: ignore this file
1034  */
file_process(void * p,uint8_t * file_data,int data_size,FilePosition position,bool upload,bool suspend_block_verdict,bool do_flush)1035 static int file_process( void* p, uint8_t* file_data, int data_size,
1036         FilePosition position, bool upload, bool suspend_block_verdict, bool do_flush)
1037 {
1038     FileContext* context;
1039     SAVE_DAQ_PKT_HDR(p);
1040     int fileverdict;
1041 #if defined(DAQ_VERSION) && DAQ_VERSION > 9
1042     uint64_t start = 0, end = 0;
1043 #endif
1044 
1045     FILE_DEBUG("Processing file data:: size:%d, position:%d, direction:%d, flush:%d",data_size,position,upload,do_flush);
1046 
1047     /* if both disabled, return immediately*/
1048     if (!is_file_service_enabled())
1049     {
1050         FILE_DEBUG("File service not enabled.");
1051         return 0;
1052     }
1053 
1054     if (position == SNORT_FILE_POSITION_UNKNOWN)
1055         return 0;
1056     FILE_REG_DEBUG_WRAP(DumpHexFile(stdout, file_data, data_size);)
1057 
1058     context = find_main_file_context(p, position, upload);
1059     if((context->file_state.sig_state == FILE_SIG_FLUSH) && context->sha256)
1060     {
1061         SnortPreprocFree(context->sha256, sizeof(SHA256_HASH_SIZE), PP_FILE,
1062                 PP_MEM_CATEGORY_SESSION);
1063         context->sha256 = NULL;
1064     }
1065     if(do_flush)
1066         context->file_state.sig_state = FILE_SIG_FLUSH;
1067     else
1068     {
1069         context->file_state.sig_state = FILE_SIG_PROCESSING;
1070     }
1071 
1072 #if defined(DAQ_VERSION) && DAQ_VERSION > 9
1073     Packet *pkt = (Packet *)p;
1074     if ( pkt && pkt->pkth && (pkt->pkth->flags & DAQ_PKT_FLAG_DEBUG_ON))
1075     {
1076        get_clockticks(start);
1077        fileverdict = process_file_context(context, p, file_data, data_size, position,suspend_block_verdict);
1078        get_clockticks(end);
1079        print_flow(p,"PROCESS_FILE_CONTEXT",0,start,end);
1080     }
1081     else
1082        fileverdict = process_file_context(context, p, file_data, data_size, position,suspend_block_verdict);
1083 #else
1084     fileverdict = process_file_context(context, p, file_data, data_size, position,suspend_block_verdict);
1085 #endif
1086 
1087     return fileverdict;
1088 }
1089 
set_file_name(void * ssnptr,uint8_t * fname,uint32_t name_size,bool save_in_context)1090 static void set_file_name (void* ssnptr, uint8_t* fname, uint32_t name_size,
1091         bool save_in_context)
1092 {
1093     FileContext* context = get_current_file_context(ssnptr);
1094     file_name_set(context, fname, name_size, save_in_context);
1095     FILE_REG_DEBUG_WRAP(printFileContext(context);)
1096 }
1097 
1098 /*
1099  *  set_file_partial API, used to mark a file partial/incomplete.
1100  *  This information is required by FW signature lookup for FTP PP
1101  *  See CSCvi28409 for more details.
1102  */
set_file_partial(void * p,FilePosition position,bool upload,bool is_partial)1103 static void set_file_partial(void *p, FilePosition position,bool upload, bool is_partial)
1104 {
1105     SAVE_DAQ_PKT_HDR(p);
1106     FileContext *context = find_main_file_context(p,position,upload);
1107     FILE_DEBUG("Partial file: %d",is_partial);
1108     context->partial_file = is_partial;
1109 }
1110 
1111 /* Return 1: file name available,
1112  *        0: file name is unavailable
1113  */
get_file_name(void * ssnptr,uint8_t ** fname,uint32_t * name_size)1114 static int get_file_name (void* ssnptr, uint8_t **fname, uint32_t *name_size)
1115 {
1116     return file_name_get(get_current_file_context(ssnptr), fname, name_size);
1117 }
1118 
get_file_size(void * ssnptr)1119 static uint64_t  get_file_size(void* ssnptr)
1120 {
1121     return file_size_get(get_current_file_context(ssnptr));
1122 }
1123 
get_file_processed_size(void * ssnptr)1124 static uint64_t  get_file_processed_size(void* ssnptr)
1125 {
1126     FileContext *context = get_main_file_context(ssnptr);
1127     if (context)
1128         return (context->processed_bytes);
1129     else
1130         return 0;
1131 }
1132 
set_file_direction(void * ssnptr,bool upload)1133 static void set_file_direction(void* ssnptr, bool upload)
1134 {
1135     file_direction_set(get_current_file_context(ssnptr),upload);
1136 }
1137 
get_file_direction(void * ssnptr)1138 static bool get_file_direction(void* ssnptr)
1139 {
1140     return file_direction_get(get_current_file_context(ssnptr));
1141 }
1142 
get_file_sig_sha256(void * ssnptr)1143 static uint8_t *get_file_sig_sha256(void* ssnptr)
1144 {
1145     return file_sig_sha256_get(get_current_file_context(ssnptr));
1146 }
1147 
set_file_policy_callback(File_policy_callback_func policy_func_cb)1148 static void set_file_policy_callback(File_policy_callback_func policy_func_cb)
1149 {
1150     new_config.file_policy_cb = policy_func_cb;
1151 }
1152 
1153 /*
1154  * - Only accepts 1 (ONE) callback being registered.
1155  *
1156  * - Call with NULL callback to "force" (guarantee) file type identification.
1157  *
1158  * TBD: Remove per-context "file_type_enabled" checking to simplify implementation.
1159  *
1160  */
enable_file_type(struct _SnortConfig * sc,File_type_callback_func callback)1161 static void enable_file_type(struct _SnortConfig* sc, File_type_callback_func callback)
1162 {
1163     new_config.file_type_id_enabled = true;
1164     start_file_processing(sc, false);
1165     LogMessage("File service: file type enabled.\n");
1166 
1167     if (!callback)
1168     {
1169         file_type_force = true;
1170     }
1171     else if(!new_config.file_type_cb)
1172     {
1173         new_config.file_type_cb = callback;
1174     }
1175     else if(new_config.file_type_cb != callback)
1176     {
1177         FatalError("Attempt to register multiple file_type callbacks.");
1178     }
1179 }
1180 
1181 /* set file signature callback function*/
enable_file_signature(struct _SnortConfig * sc,File_signature_callback_func callback)1182 static void enable_file_signature(struct _SnortConfig* sc, File_signature_callback_func callback)
1183 {
1184 
1185     new_config.file_signature_enabled = true;
1186     start_file_processing(sc, false);
1187 
1188     if(!new_config.file_signature_cb)
1189     {
1190         new_config.file_signature_cb = callback;
1191         LogMessage("File service: file signature enabled.\n");
1192     }
1193     else if(new_config.file_signature_cb != callback)
1194     {
1195         WarningMessage("File service: signature callback redefined.\n");
1196     }
1197 }
1198 
1199 /* Enable file capture, also enable file signature */
enable_file_capture(struct _SnortConfig * sc,File_signature_callback_func callback)1200 static void enable_file_capture(struct _SnortConfig* sc, File_signature_callback_func callback)
1201 {
1202     new_config.file_capture_enabled = true;
1203     LogMessage("File service: file capture enabled.\n");
1204     start_file_processing(sc, true);
1205     /* Enable file signature*/
1206     enable_file_signature(sc, callback);
1207 }
1208 
set_file_action_log_callback(Log_file_action_func log_func)1209 static void set_file_action_log_callback(Log_file_action_func log_func)
1210 {
1211     new_config.log_file_action = log_func;
1212 }
1213 
1214 /* Get maximal file depth based on configuration
1215  * This function must be called after all file services are configured/enabled.
1216  */
get_max_file_depth(struct _SnortConfig * sc,bool next)1217 static int64_t get_max_file_depth(struct _SnortConfig *sc, bool next)
1218 {
1219     FileConfig *file_config;
1220     FileServiceConfig *fs_config;
1221 
1222     if (!sc)
1223         sc = snort_conf;
1224     file_config =  (FileConfig *)(sc->file_config);
1225     fs_config = next ? &new_config:&cur_config;
1226 
1227     if (!file_config)
1228         return -1;
1229 
1230      /* If next is set, proceed further to check the depth */
1231     if (!next && file_config->file_depth)
1232         return file_config->file_depth;
1233 
1234     file_config->file_depth = -1;
1235 
1236 
1237     if (fs_config->file_type_id_enabled)
1238     {
1239         file_config->file_depth = file_config->file_type_depth;
1240     }
1241 
1242     if (fs_config->file_signature_enabled)
1243     {
1244         if (file_config->file_signature_depth > file_config->file_depth)
1245             file_config->file_depth = file_config->file_signature_depth;
1246     }
1247 
1248     if (file_config->file_depth > 0)
1249     {
1250         /*Extra byte for deciding whether file data will be over limit*/
1251         file_config->file_depth++;
1252         return (file_config->file_depth);
1253     }
1254     else
1255     {
1256         return -1;
1257     }
1258 }
1259 
is_file_signature_enabled()1260 static bool is_file_signature_enabled()
1261 {
1262     return cur_config.file_signature_enabled;
1263 }
1264 
get_file_position(void * pkt)1265 static FilePosition get_file_position(void *pkt)
1266 {
1267     FilePosition position = SNORT_FILE_POSITION_UNKNOWN;
1268     Packet *p = (Packet *)pkt;
1269     SAVE_DAQ_PKT_HDR(p);
1270 
1271     if(ScPafEnabled())
1272     {
1273         if (PacketHasFullPDU(p))
1274             position = SNORT_FILE_FULL;
1275         else if (PacketHasStartOfPDU(p))
1276             position = SNORT_FILE_START;
1277         else if (p->packet_flags & PKT_PDU_TAIL)
1278             position = SNORT_FILE_END;
1279         else if (get_file_processed_size(p->ssnptr))
1280             position = SNORT_FILE_MIDDLE;
1281     }
1282 
1283     return position;
1284 }
1285 
1286 /*
1287  *  This function determines whether we shold abort PAF.  Will return
1288  *  true if the current packet is midstream, or unestablisted session
1289  *
1290  *  PARAMS:
1291  *      uint32_t - session flags passed in to callback.
1292  *
1293  *  RETURNS:
1294  *      true - if we should abort paf
1295  *      false - if we should continue using paf
1296  */
check_paf_abort(void * ssn)1297 static bool check_paf_abort(void* ssn)
1298 {
1299     uint32_t flags = session_api->get_session_flags(ssn);
1300     if (flags & SSNFLAG_MIDSTREAM)
1301     {
1302         FILE_DEBUG("Aborting PAF because of midstream pickup.");
1303         return true;
1304     }
1305     else if (!(flags & SSNFLAG_ESTABLISHED))
1306     {
1307         FILE_DEBUG("Aborting PAF because of unestablished session.");
1308         return true;
1309     }
1310     return false;
1311 }
1312 
get_max_file_capture_size(void * ssn)1313 static int64_t get_max_file_capture_size(void *ssn)
1314 {
1315     if (snort_conf->file_config)
1316         return snort_conf->file_config->file_capture_max_size;
1317 
1318     return 0;
1319 }
1320 
str_to_hash(uint8_t * str,int length)1321 static uint32_t str_to_hash(uint8_t *str, int length )
1322 {
1323     uint32_t a,b,c,tmp;
1324     int i,j,k,l;
1325     a = b = c = 0;
1326     for (i=0,j=0;i<length;i+=4)
1327     {
1328         tmp = 0;
1329         k = length - i;
1330         if (k > 4)
1331             k=4;
1332 
1333         for (l=0;l<k;l++)
1334         {
1335             tmp |= *(str + i + l) << l*8;
1336         }
1337 
1338         switch (j)
1339         {
1340         case 0:
1341             a += tmp;
1342             break;
1343         case 1:
1344             b += tmp;
1345             break;
1346         case 2:
1347             c += tmp;
1348             break;
1349         }
1350         j++;
1351 
1352         if (j == 3)
1353         {
1354             mix(a,b,c);
1355             j = 0;
1356         }
1357     }
1358     final(a,b,c);
1359     return c;
1360 }
1361 
file_config_malware_check(void * ssnptr,uint16_t app_id)1362 bool file_config_malware_check(void *ssnptr, uint16_t app_id)
1363 {
1364 	uint32_t policy_flags = 0;
1365 	if (cur_config.file_policy_cb)
1366 	{
1367         //Upload
1368 	    policy_flags = cur_config.file_policy_cb(ssnptr, app_id, true);
1369         if ( (policy_flags & ENABLE_FILE_SIGNATURE_SHA256) || (policy_flags & ENABLE_FILE_TYPE_IDENTIFICATION) )
1370             return true;
1371 
1372         //Download
1373 	        policy_flags = cur_config.file_policy_cb(ssnptr, app_id, false);
1374         if ( (policy_flags & ENABLE_FILE_SIGNATURE_SHA256) || (policy_flags & ENABLE_FILE_TYPE_IDENTIFICATION) )
1375             return true;
1376    }
1377    return false;
1378 }
1379 
get_character_encoding(uint8_t * buffer,uint32_t length)1380 static FileCharEncoding get_character_encoding(uint8_t *buffer, uint32_t length)
1381 {
1382     FileCharEncoding encoding = SNORT_CHAR_ENCODING_ASCII;
1383 
1384     if(length > UTF_16_LE_BOM_LEN)
1385     {
1386         if(memcmp(buffer, UTF_16_LE_BOM, UTF_16_LE_BOM_LEN) == 0)
1387             encoding = SNORT_CHAR_ENCODING_UTF_16LE;
1388         else if(memcmp(buffer, UTF_16_BE_BOM, UTF_16_BE_BOM_LEN) == 0)
1389             encoding = SNORT_CHAR_ENCODING_UTF_16BE;
1390     }
1391 
1392     return encoding;
1393 }
1394 
1395  /* It generates the file event if event logging is enabled. */
file_event_log_dump(FileCache * fileCache,void * p,uint64_t file_id)1396 void file_event_log_dump(FileCache *fileCache, void* p, uint64_t file_id)
1397 {
1398     FileEntry *fileEntry;
1399 
1400     fileEntry = file_cache_get(fileCache, p, file_id, true);
1401 
1402     if (NULL != fileEntry && fileEntry->context)
1403     {
1404         Packet *pkt = (Packet *)p;
1405 
1406         if (FILE_VERDICT_LOG == fileEntry->context->verdict &&
1407                 !(pkt->packet_flags & PKT_FILE_EVENT_SET))
1408         {
1409             file_eventq_add(GENERATOR_FILE_SIGNATURE, FILE_SIGNATURE_SHA256,
1410                     FILE_SIGNATURE_SHA256_STR, RULE_TYPE__ALERT);
1411             pkt->packet_flags |= PKT_FILE_EVENT_SET;
1412             fileEntry->context->file_signature_enabled = false;
1413         }
1414     }
1415 }
1416 
1417 /*      file_signature_reset  API to restore the file detection state.
1418  *      This is done because once we flush and we get a cloud verdict, all the detection states are erased.
1419  *      To ensure that we continue the detection SSL has to use this API
1420  */
file_signature_reset(void * ssnptr)1421 static void file_signature_reset (void *ssnptr)
1422 {
1423     FileContext* context = NULL;
1424     FileSession *file_session = get_file_session (ssnptr);
1425 
1426     if (file_session)
1427         context = file_session->main_context;
1428 
1429     if (!context)
1430     {
1431         ErrorMessageThrottled(&error_throttleInfo,"Failed to reset signature state: context not found.\n");
1432         return;
1433     }
1434 
1435     if (context->file_state.sig_state == FILE_SIG_FLUSH)
1436     {
1437         context->file_signature_enabled = true;
1438         context->file_state.sig_state = FILE_SIG_PROCESSING;
1439         context->verdict = FILE_VERDICT_UNKNOWN;
1440         if (context->sha256)
1441         {
1442             SnortPreprocFree(context->sha256, sizeof(SHA256_HASH_SIZE), PP_FILE,
1443                     PP_MEM_CATEGORY_SESSION);
1444             context->sha256 = NULL;
1445         }
1446     }
1447     return;
1448 }
1449 
file_get_filetype(void * ssnptr)1450 static char* file_get_filetype (void *ssnptr)
1451 {
1452     FileContext *context = get_current_file_context(ssnptr);
1453 
1454     if (!context)
1455     {
1456         return NULL;
1457     }
1458 
1459 #ifdef TARGET_BASED
1460     if (cur_config.file_policy_cb)
1461     {
1462         bool policy_flags;
1463         policy_flags = cur_config.file_policy_cb(ssnptr, context->app_id, context->upload);
1464         if (!(policy_flags & ENABLE_FILE_TYPE_IDENTIFICATION))
1465         {
1466             return NULL;
1467         }
1468     }
1469 #endif
1470 
1471     return file_type_name (context->file_config, context->file_type_id);
1472 }
1473 
1474