"Fossies" - the Fresh Open Source Software Archive

Member "snort-2.9.17/src/file-process/file_service.c" (16 Oct 2020, 47796 Bytes) of package /linux/misc/snort-2.9.17.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "file_service.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.9.16.1_vs_2.9.17.

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