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