"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/file-process/file_segment_process.c" between
snort-2.9.16.1.tar.gz and snort-2.9.17.tar.gz

About: Snort is a network intrusion prevention and detection system (IDS/IPS) combining the benefits of signature, protocol and anomaly-based inspection.

file_segment_process.c  (snort-2.9.16.1):file_segment_process.c  (snort-2.9.17)
skipping to change at line 30 skipping to change at line 30
**************************************************************************** ****************************************************************************
* Author(s): Hui Cao <huica@cisco.com> * Author(s): Hui Cao <huica@cisco.com>
****************************************************************************/ ****************************************************************************/
#include "file_segment_process.h" #include "file_segment_process.h"
#include "parser.h" #include "parser.h"
#include "file_resume_block.h" #include "file_resume_block.h"
#include "file_config.h" #include "file_config.h"
#ifdef REG_TEST #ifdef REG_TEST
#include "file_stats.h"
#include "reg_test.h" #include "reg_test.h"
#include <stdio.h> #include <stdio.h>
#endif #endif
#define UNKNOWN_FILE_SIZE ~0 #define UNKNOWN_FILE_SIZE ~0
extern FileSession* get_file_session(void *ssnptr); extern FileSession* get_file_session(void *ssnptr);
static inline void file_segment_free(FileCache *fileCache, FileSegment* file_seg ment) static inline void file_segment_free(FileCache *fileCache, FileSegment* file_seg ment)
{ {
skipping to change at line 77 skipping to change at line 78
} }
static inline void file_entry_free(FileEntry *file_entry) static inline void file_entry_free(FileEntry *file_entry)
{ {
if (!file_entry) if (!file_entry)
return; return;
if (file_entry->file_name) if (file_entry->file_name)
{ {
FILE_DEBUG("File name: %s released (%p)", file_entry->file_name, file_en DEBUG_WRAP(DebugMessage(DEBUG_FILE,
try->file_name); "File name: %s released (%p)\n", file_entry->file_
name, file_entry->file_name));
free(file_entry->file_name); free(file_entry->file_name);
file_entry->file_name = NULL; file_entry->file_name = NULL;
file_entry->file_name_size = 0; file_entry->file_name_size = 0;
} }
if (file_entry->context) if (file_entry->context)
{ {
file_entry->context->attached_file_entry = NULL;
file_context_free(file_entry->context); file_context_free(file_entry->context);
file_entry->context = NULL; file_entry->context = NULL;
} }
file_entry->file_size = 0; file_entry->file_size = 0;
file_segments_free(file_entry); file_segments_free(file_entry);
} }
skipping to change at line 119 skipping to change at line 122
while (pruned < mustdie && while (pruned < mustdie &&
(sfxhash_count(fileCache->hashTable) > 0)) (sfxhash_count(fileCache->hashTable) > 0))
{ {
if ((lru_node = sfxhash_lru_node(fileCache->hashTable)) != NULL) if ((lru_node = sfxhash_lru_node(fileCache->hashTable)) != NULL)
{ {
if (lru_node->data == file) if (lru_node->data == file)
break; break;
if (sfxhash_free_node(fileCache->hashTable, lru_node) != SFXHASH_OK) if (sfxhash_free_node(fileCache->hashTable, lru_node) != SFXHASH_OK)
{ {
FILE_WARNING("failed to remove file entry from hash.");
LogMessage("WARNING: failed to remove file entry from hash.\n"); LogMessage("WARNING: failed to remove file entry from hash.\n");
break; break;
} }
pruned++; pruned++;
} }
} }
fileCache->status.prunes += pruned; fileCache->status.prunes += pruned;
return pruned; return pruned;
} }
skipping to change at line 231 skipping to change at line 233
{ {
FileSegment* ss; FileSegment* ss;
unsigned int size = sizeof(*ss); unsigned int size = sizeof(*ss);
if ( data_size > 0 ) if ( data_size > 0 )
size += (uint64_t)data_size - 1; /* ss contains 1st byte */ size += (uint64_t)data_size - 1; /* ss contains 1st byte */
else else
return NULL; return NULL;
/* Check against memcap here*/ /* Check against memcap here*/
if ((fileCache->status.segment_mem_in_use + size) > fileCache->file_segme nt_memcap) if ((fileCache->status.segment_mem_in_use + size) > fileCache->file_segment_ memcap)
{ {
/* make more memory available by pruning. Return NULL if nothing is prun ed*/ /* make more memory available by pruning. Return NULL if nothing is prun ed*/
if(pruneFileCache(fileCache, file) == 0) if(pruneFileCache(fileCache, file) == 0)
return NULL; return NULL;
else if ((fileCache->status.segment_mem_in_use + size) > fileCache->file
_segment_memcap)
return NULL;
} }
fileCache->status.segment_mem_in_use += size; fileCache->status.segment_mem_in_use += size;
ss = (FileSegment*) SnortAlloc(size); ss = (FileSegment*) SnortAlloc(size);
ss->segment_size = size; ss->segment_size = size;
ss->size = data_size; ss->size = data_size;
ss->offset = offset; ss->offset = offset;
memcpy(ss->data, file_data, data_size); memcpy(ss->data, file_data, data_size);
if (fileCache->status.segment_mem_in_use_max < fileCache->status.segment_mem _in_use) if (fileCache->status.segment_mem_in_use_max < fileCache->status.segment_mem _in_use)
{ {
fileCache->status.segment_mem_in_use_max = fileCache->status.segment_mem _in_use; fileCache->status.segment_mem_in_use_max = fileCache->status.segment_mem _in_use;
skipping to change at line 273 skipping to change at line 277
int data_size, FileEntry *file) int data_size, FileEntry *file)
{ {
FileSegment *current_segment = file->segments; FileSegment *current_segment = file->segments;
uint64_t start = offset; uint64_t start = offset;
uint64_t end = offset + data_size; uint64_t end = offset + data_size;
FileSegment *new_segment; FileSegment *new_segment;
/* left points to segment that "next" pointer needs to be updated */ /* left points to segment that "next" pointer needs to be updated */
FileSegment *left = NULL; FileSegment *left = NULL;
FileSegment *previous = NULL; FileSegment *previous = NULL;
bool find_left = false; bool find_left = false;
bool is_overlap = false;
/* Create a new segment first */
new_segment = file_segment_alloc(fileCache, file_data, data_size, offset, fi
le);
if (!new_segment)
{
FILE_ERROR("Failed to allocate new file segment");
return 0;
}
/* First segment to store*/
if (!current_segment)
{
file->segments = new_segment;
return 1;
}
/* Find left boundary, left points to segment that needs update*/ /* Find left boundary, left points to segment that needs update*/
while (current_segment) while (current_segment)
{ {
if (current_segment->offset > start) if (current_segment->offset > start)
{ {
find_left = true; find_left = true;
left = previous; left = previous;
break; break;
} }
previous = current_segment; previous = current_segment;
current_segment = current_segment->next; current_segment = current_segment->next;
} }
/* New segment should be at the end of link list*/ if (find_left)
if (!find_left)
{ {
previous->next = new_segment; if (!left)
}
/* New segment should be at the start of link list*/
else if (left == NULL)
{
if (end <= file->segments->offset)
{ {
new_segment->next = file->segments; /* Need to insert at begining */
file->segments = new_segment; if (end > file->segments->offset)
{
/* Overlap, trim off exrta data from end */
data_size = file->segments->offset - offset;
}
} }
else else
{ {
is_overlap = true; /* Need to insert in the middle */
if (left->offset + left->size > start)
{
/* Overlap, trim begining */
offset = left->offset +left->size;
data_size = end - offset;
file_data = file_data + offset - start;
}
if (left->next->offset < end)
{
/* Overlap, trim end of data */
data_size = left->next->offset - offset;
}
} }
} }
else else if (previous)
{ {
if ((left->offset + left->size > start) || /* Need to insert at end */
(left->next->offset < end)) left = previous;
{ if (left->offset + left->size > start)
is_overlap = true;
}
else
{ {
new_segment->next = left->next; /* Overlap, trim begining */
left->next = new_segment; offset = left->offset + left->size;
data_size = end - offset;
file_data = file_data + offset - start;
} }
} }
if (data_size > 0)
/* ignore overlap case */ {
if (is_overlap) new_segment = file_segment_alloc(fileCache, file_data, data_size, offset
, file);
if (!new_segment)
return 0;
}
else
{ {
file_segment_free(fileCache, new_segment); /* data_size <= 0 means a complete coverlapped segment we have already s
FILE_ERROR("Overlapping segments"); een */
FILE_DEBUG("Complete overlapped segment, discarding.");
return 0; return 0;
} }
if (!left)
{
/* inserting at begining or list is empty */
new_segment->next = file->segments;
file->segments = new_segment;
}
else
{
/* inserting at end or middle */
new_segment->next = left->next;
left->next = new_segment;
}
return 1; return 1;
} }
static inline FilePosition get_file_position(uint64_t file_size, int data_size, static inline FilePosition get_file_position(uint64_t file_size, int data_size,
uint64_t offset) uint64_t offset)
{ {
if (offset == 0) if (offset == 0)
{ {
if (file_size == (uint64_t) data_size) if (file_size == (uint64_t) data_size)
return SNORT_FILE_FULL; return SNORT_FILE_FULL;
skipping to change at line 446 skipping to change at line 457
/* Create file cache */ /* Create file cache */
FileCache *file_cache_create(uint64_t memcap, uint32_t cleanup_files) FileCache *file_cache_create(uint64_t memcap, uint32_t cleanup_files)
{ {
FileCache *fileCache = NULL; FileCache *fileCache = NULL;
int max_files = 0; int max_files = 0;
uint64_t file_segment_memcap = memcap/2; uint64_t file_segment_memcap = memcap/2;
if( !memcap ) if( !memcap )
{ {
FILE_WARNING("File cache memory unlimited!");
WarningMessage("%s(%d) File cache memory unlimited!\n", WarningMessage("%s(%d) File cache memory unlimited!\n",
file_name, file_line); file_name, file_line);
} }
/* Half for file segment, half for file context tracking*/ /* Half for file segment, half for file context tracking*/
max_files = get_max_files_from_memcap(memcap - file_segment_memcap); max_files = get_max_files_from_memcap(memcap - file_segment_memcap);
fileCache = SnortAlloc( sizeof( *fileCache ) ); fileCache = SnortAlloc( sizeof( *fileCache ) );
if( fileCache ) if( fileCache )
{ {
fileCache->max_files = max_files; fileCache->max_files = max_files;
/* Okay, now create the table */ /* Okay, now create the table */
fileCache->hashTable = sfxhash_new(max_files, sizeof(FileKey), sizeof(Fi leEntry), fileCache->hashTable = sfxhash_new(max_files, sizeof(FileKey), sizeof(Fi leEntry),
0, 0, NULL, file_entry_free_func, 1 ); 0, 0, NULL, file_entry_free_func, 1 );
if (!fileCache->hashTable) if (!fileCache->hashTable)
{ {
FILE_CRITICAL("Unable to create a file cache.");
FatalError( "%s(%d) Unable to create a file cache.\n", file_name, fi le_line); FatalError( "%s(%d) Unable to create a file cache.\n", file_name, fi le_line);
} }
sfxhash_set_max_nodes( fileCache->hashTable, max_files ); sfxhash_set_max_nodes( fileCache->hashTable, max_files );
fileCache->file_segment_memcap = file_segment_memcap; fileCache->file_segment_memcap = file_segment_memcap;
fileCache->cleanup_files = cleanup_files; fileCache->cleanup_files = cleanup_files;
} }
else else
{ {
FILE_CRITICAL("Unable to create a file cache.");
FatalError( "%s(%d) Unable to create a file cache.\n", FatalError( "%s(%d) Unable to create a file cache.\n",
file_name, file_line); file_name, file_line);
} }
return fileCache; return fileCache;
} }
/* Release file cache */ /* Release file cache */
void file_cache_free( FileCache *fileCache ) void file_cache_free( FileCache *fileCache )
{ {
skipping to change at line 555 skipping to change at line 563
if (!file_api->set_current_file_context(ssnptr, context)) if (!file_api->set_current_file_context(ssnptr, context))
return; return;
file_session = get_file_session (ssnptr); file_session = get_file_session (ssnptr);
if (!file_session->file_cache) if (!file_session->file_cache)
file_session->file_cache = fileCache; file_session->file_cache = fileCache;
file_session->file_id = file_id; file_session->file_id = file_id;
FILE_DEBUG("Updated file_id: %u",file_id); FILE_DEBUG("Updated file_id: %u, file cache %p in file session %p",file_id, fileCache, file_session);
} }
/* /*
* Process file segment, do file segment reassemble if the file segment is * Process file segment, do file segment reassemble if the file segment is
* out of order. file_id is unique, used as a key to find the file entity. * out of order. file_id is unique, used as a key to find the file entity.
* Return: * Return:
* 1: continue processing/log/block this file * 1: continue processing/log/block this file
* 0: ignore this file segment * 0: ignore this file segment
*/ */
int file_segment_process( FileCache *fileCache, void* p, uint64_t file_id, int file_segment_process( FileCache *fileCache, void* p, uint64_t file_id,
skipping to change at line 589 skipping to change at line 597
if (fileEntry == NULL) if (fileEntry == NULL)
{ {
FILE_ERROR("Processing segment failed: no file entry in cache"); FILE_ERROR("Processing segment failed: no file entry in cache");
return 0; return 0;
} }
if (!fileEntry->context) if (!fileEntry->context)
fileEntry->file_resume_check = true; fileEntry->file_resume_check = true;
if(offset == 0)
fileEntry->file_resume_check = false;
if(fileEntry->file_resume_check) if(fileEntry->file_resume_check)
{ {
if(fileEntry->file_name_size > 0) if(fileEntry->file_name_size > 0)
{ {
file_sig = file_api->str_to_hash(fileEntry->file_name, fileEntry->fi le_name_size); file_sig = file_api->str_to_hash(fileEntry->file_name, fileEntry->fi le_name_size);
} }
else if(fileEntry->context && fileEntry->context->file_name_size > 0 && fileEntry->context->file_name) else if(fileEntry->context && fileEntry->context->file_name_size > 0 && fileEntry->context->file_name)
{ {
file_sig = file_api->str_to_hash(fileEntry->context->file_name, file Entry->context->file_name_size); file_sig = file_api->str_to_hash(fileEntry->context->file_name, file Entry->context->file_name_size);
} }
skipping to change at line 644 skipping to change at line 649
} }
if (!fileEntry->file_cache) if (!fileEntry->file_cache)
fileEntry->file_cache = fileCache; fileEntry->file_cache = fileCache;
if (!fileEntry->context) if (!fileEntry->context)
{ {
fileEntry->context = file_api->create_file_context(ssnptr); fileEntry->context = file_api->create_file_context(ssnptr);
file_api->init_file_context(ssnptr, upload, fileEntry->context); file_api->init_file_context(ssnptr, upload, fileEntry->context);
fileEntry->context->file_id = (uint32_t)file_id; fileEntry->context->file_id = (uint32_t)file_id;
fileEntry->context->attached_file_entry = fileEntry;
update_file_session(ssnptr, fileCache, file_id, fileEntry->context);
file_name_set(fileEntry->context, fileEntry->file_name, fileEntry->file_
name_size, true);
} }
else if (fileEntry->context->verdict != FILE_VERDICT_UNKNOWN && !fileEntry-> context->smb_unknown_file_size) else if (fileEntry->context->verdict != FILE_VERDICT_UNKNOWN && !fileEntry-> context->smb_unknown_file_size)
{ {
/*A new file session, but policy might be different*/ /*A new file session, but policy might be different*/
file_api->init_file_context(ssnptr, upload, fileEntry->context);
if (((fileEntry->context->sha256)) if (((fileEntry->context->sha256))
|| !fileEntry->context->file_signature_enabled ) || !fileEntry->context->file_signature_enabled )
{ {
/* Just check file type and signature */ /* Just check file type and signature */
update_file_session(ssnptr, fileCache, file_id, fileEntry->context); return _process_one_file_segment(p, fileEntry, file_data, &data_size
ret = _process_one_file_segment(p, fileEntry, file_data, &data_size, , file_size);
file_size);
goto resume_block;
}
if (offset == 0)
{
fileEntry->offset = 0;
fileEntry->context->file_id = (uint32_t)file_id;
} }
} }
if(offset < fileEntry->offset && offset + data_size > fileEntry->offset) if(offset < fileEntry->offset && offset + data_size > fileEntry->offset)
{ {
file_data += (fileEntry->offset - offset); file_data += (fileEntry->offset - offset);
data_size = (offset + data_size)-fileEntry->offset; data_size = (offset + data_size)-fileEntry->offset;
offset = fileEntry->offset; offset = fileEntry->offset;
} }
/* Walk through the segments that can be flushed*/ /* Walk through the segments that can be flushed*/
if (fileEntry->offset == offset) if (fileEntry->offset == offset)
{ {
/*Process the packet update the offset */ /*Process the packet update the offset */
update_file_session(ssnptr, fileCache, file_id, fileEntry->context);
ret = _process_one_file_segment(p, fileEntry, file_data, &data_size, fil e_size); ret = _process_one_file_segment(p, fileEntry, file_data, &data_size, fil e_size);
fileEntry->offset += data_size; fileEntry->offset += data_size;
if (!ret) if (!ret)
{ {
file_segments_free(fileEntry); file_segments_free(fileEntry);
return 0; return 0;
} }
ret = _process_file_segments(fileCache, p, fileEntry, file_size); ret = _process_file_segments(fileCache, p, fileEntry, file_size);
} }
else if ((fileEntry->offset < file_size) && (fileEntry->offset < offset)) else if ((fileEntry->offset < file_size) && (fileEntry->offset < offset))
{ {
ret = _file_segments_update(fileCache, file_data, offset, data_size, fil eEntry); ret = _file_segments_update(fileCache, file_data, offset, data_size, fil eEntry);
} }
#ifdef REG_TEST
if(ret && fileEntry->file_name_size) if(ret && fileEntry->file_name_size)
{ {
update_file_session(ssnptr, fileCache, file_id, fileEntry->context); FILE_REG_DEBUG_WRAP(printFileContext(fileEntry->context));
file_api->set_file_name(ssnptr, fileEntry->file_name, fileEntry->file_na
me_size, true);
fileEntry->file_name_size = 0; fileEntry->file_name_size = 0;
} }
#endif
resume_block:
verdict = fileEntry->context->verdict;
/* Add to resume queue if it is blocked */
if((verdict == FILE_VERDICT_BLOCK) || (verdict == FILE_VERDICT_REJECT))
{
FileConfig *file_config = (FileConfig *)(snort_conf->file_config);
if(fileEntry->file_name_size > 0)
{
file_sig = file_api->str_to_hash(fileEntry->file_name, fileEntry->fi
le_name_size);
}
else if(fileEntry->context->file_name_size > 0 && fileEntry->context->fi
le_name)
{
file_sig = file_api->str_to_hash(fileEntry->context->file_name, file
Entry->context->file_name_size);
}
file_resume_block_add_file(p, file_sig,
(uint32_t)file_config->file_block_timeout,
verdict, fileEntry->context->file_type_id, fileEntry->context->s
ha256, 0, 0, true, 0);
}
return ret; return ret;
} }
/* Return the status of file cache */ /* Return the status of file cache */
FileCacheStatus *file_cache_status(FileCache *fileCache) FileCacheStatus *file_cache_status(FileCache *fileCache)
{ {
return (&(fileCache->status)); return (&(fileCache->status));
} }
static bool file_cache_prune_files(FileCache *fileCache, uint8_t *pWork) static bool file_cache_prune_files(FileCache *fileCache, uint8_t *pWork)
 End of changes. 31 change blocks. 
94 lines changed or deleted 72 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)