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. Hcao
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 #include "sf_types.h"
33 #include "file_lib.h"
34 #include "file_identifier.h"
35 #include "file_config.h"
36 #include <sys/types.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include "sf_sechash.h"
41 #include "memory_stats.h"
42 
43 #include "util.h"
44 #include "file_capture.h"
45 
get_data_size_from_depth_limit(FileContext * context,FileProcessType type,int data_size)46 static inline int get_data_size_from_depth_limit(FileContext* context, FileProcessType type, int data_size)
47 {
48     FileConfig *file_config =  (FileConfig *)context->file_config;
49     uint64_t max_depth;
50 
51     if (!file_config)
52         return data_size;
53 
54     switch(type)
55     {
56     case SNORT_FILE_TYPE_ID:
57         max_depth = file_config->file_type_depth;
58         break;
59     case SNORT_FILE_SHA256:
60         max_depth = file_config->file_signature_depth;
61         break;
62     default:
63         return data_size;
64     }
65 
66     if (context->processed_bytes > max_depth)
67         data_size = -1;
68     else if (context->processed_bytes + data_size > max_depth)
69         data_size = (int)(max_depth - context->processed_bytes);
70 
71     return data_size;
72 
73 }
74 
75 /* stop file type identification */
_finalize_file_type(FileContext * context)76 static inline void _finalize_file_type (FileContext* context)
77 {
78     if (SNORT_FILE_TYPE_CONTINUE ==  context->file_type_id)
79         context->file_type_id = SNORT_FILE_TYPE_UNKNOWN;
80     context->file_type_context = NULL;
81 }
82 /*
83  * Main File type processing function
84  * We use file type context to decide file type across packets
85  *
86  * File type detection is completed either when
87  * 1) file is completed or
88  * 2) file type depth is reached or
89  * 3) file magics are exhausted in depth
90  *
91  */
file_type_id(FileContext * context,uint8_t * file_data,int size,FilePosition position)92 void file_type_id( FileContext* context, uint8_t* file_data,
93         int size, FilePosition position)
94 {
95     int data_size;
96 
97     if (!context)
98         return;
99 
100     /* file type already found and no magics to continue*/
101     if (context->file_type_id && !context->file_type_context)
102         return;
103 
104     /* Check whether file type depth is reached*/
105     data_size = get_data_size_from_depth_limit(context, SNORT_FILE_TYPE_ID, size);
106 
107     if (data_size < 0)
108     {
109         _finalize_file_type(context);
110         return;
111     }
112 
113     file_identifiers_match(file_data, data_size, context);
114 
115     /* Check whether file transfer is done or type depth is reached*/
116     if ( (position == SNORT_FILE_END)  || (position == SNORT_FILE_FULL) ||
117          (data_size != size) )
118     {
119         _finalize_file_type(context);
120     }
121 }
122 
file_signature_sha256(FileContext * context,uint8_t * file_data,int size,FilePosition position)123 void file_signature_sha256(FileContext* context, uint8_t* file_data,
124         int size, FilePosition position)
125 {
126     int data_size;
127 
128     if (!context)
129         return;
130 
131     data_size = get_data_size_from_depth_limit(context, SNORT_FILE_SHA256, size);
132 
133     if (data_size != size)
134     {
135         context->file_state.sig_state = FILE_SIG_DEPTH_FAIL;
136         return;
137     }
138 
139     switch (position)
140     {
141     case SNORT_FILE_START:
142         if (!context->file_signature_context)
143             context->file_signature_context = SnortPreprocAlloc(1, sizeof(SHA256CONTEXT), PP_FILE, PP_MEM_CATEGORY_SESSION);
144 
145         SHA256INIT((SHA256CONTEXT *)context->file_signature_context);
146         SHA256UPDATE((SHA256CONTEXT *)context->file_signature_context, file_data, data_size);
147         if(context->file_state.sig_state == FILE_SIG_FLUSH)
148         {
149             static uint8_t file_signature_context_backup[sizeof(SHA256CONTEXT)];
150             context->sha256 = SnortPreprocAlloc(1, SHA256_HASH_SIZE, PP_FILE, PP_MEM_CATEGORY_SESSION);
151             memcpy(file_signature_context_backup, context->file_signature_context, sizeof(SHA256CONTEXT));
152 
153             SHA256FINAL(context->sha256, (SHA256CONTEXT *)context->file_signature_context);
154             memcpy(context->file_signature_context, file_signature_context_backup, sizeof(SHA256CONTEXT));
155         }
156         break;
157     case SNORT_FILE_MIDDLE:
158         if (!context->file_signature_context)
159             context->file_signature_context = SnortPreprocAlloc(1, sizeof(SHA256CONTEXT), PP_FILE, PP_MEM_CATEGORY_SESSION);
160         SHA256UPDATE((SHA256CONTEXT *)context->file_signature_context, file_data, data_size);
161         if(context->file_state.sig_state == FILE_SIG_FLUSH)
162         {
163             static uint8_t file_signature_context_backup[sizeof(SHA256CONTEXT)];
164             if(!context->sha256)
165                 context->sha256 = SnortPreprocAlloc(1, SHA256_HASH_SIZE, PP_FILE, PP_MEM_CATEGORY_SESSION);
166             memcpy(file_signature_context_backup, context->file_signature_context, sizeof(SHA256CONTEXT));
167 
168             SHA256FINAL(context->sha256, (SHA256CONTEXT *)context->file_signature_context);
169             memcpy(context->file_signature_context, file_signature_context_backup, sizeof(SHA256CONTEXT));
170         }
171         break;
172     case SNORT_FILE_END:
173         if (!context->file_signature_context)
174             context->file_signature_context = SnortPreprocAlloc(1, sizeof(SHA256CONTEXT), PP_FILE, PP_MEM_CATEGORY_SESSION);
175         if (context->processed_bytes == 0)
176             SHA256INIT((SHA256CONTEXT *)context->file_signature_context);
177         SHA256UPDATE((SHA256CONTEXT *)context->file_signature_context, file_data, data_size);
178         if(!context->sha256)
179             context->sha256 = SnortPreprocAlloc(1, SHA256_HASH_SIZE, PP_FILE, PP_MEM_CATEGORY_SESSION);
180         SHA256FINAL(context->sha256, (SHA256CONTEXT *)context->file_signature_context);
181         context->file_state.sig_state = FILE_SIG_DONE;
182         break;
183     case SNORT_FILE_FULL:
184         if (!context->file_signature_context)
185             context->file_signature_context = SnortPreprocAlloc(1, sizeof(SHA256CONTEXT), PP_FILE, PP_MEM_CATEGORY_SESSION);
186         SHA256INIT((SHA256CONTEXT *)context->file_signature_context);
187         SHA256UPDATE((SHA256CONTEXT *)context->file_signature_context, file_data, data_size);
188         if(!context->sha256)
189             context->sha256 = SnortPreprocAlloc(1, SHA256_HASH_SIZE, PP_FILE, PP_MEM_CATEGORY_SESSION);
190         SHA256FINAL(context->sha256, (SHA256CONTEXT *)context->file_signature_context);
191         context->file_state.sig_state = FILE_SIG_DONE;
192         break;
193     default:
194         break;
195     }
196 }
197 
198 /*File context management*/
199 
file_context_create(void)200 FileContext *file_context_create(void)
201 {
202     FileContext *context = (FileContext *)SnortPreprocAlloc(1, sizeof(*context), PP_FILE, PP_MEM_CATEGORY_SESSION);
203     return (context);
204 }
205 
cleanDynamicContext(FileContext * context)206 static inline void cleanDynamicContext (FileContext *context)
207 {
208     if (context->file_signature_context)
209         SnortPreprocFree(context->file_signature_context, sizeof(SHA256CONTEXT), PP_FILE, PP_MEM_CATEGORY_SESSION);
210     if(context->sha256)
211         SnortPreprocFree(context->sha256, SHA256_HASH_SIZE, PP_FILE, PP_MEM_CATEGORY_SESSION);
212     if(context->file_capture)
213         file_capture_stop(context);
214     if(context->file_name && context->file_name_saved)
215         SnortPreprocFree(context->file_name, context->file_name_size, PP_FILE, PP_MEM_CATEGORY_SESSION);
216 }
217 
file_context_reset(FileContext * context)218 void file_context_reset(FileContext *context)
219 {
220     cleanDynamicContext(context);
221     memset(context, 0, sizeof(*context));
222 
223 }
224 
file_context_free(void * ctx)225 void file_context_free(void *ctx)
226 {
227     FileContext *context = (FileContext *)ctx;
228     if (!context || context->attached_file_entry)
229         return;
230     cleanDynamicContext(context);
231     SnortPreprocFree(context, sizeof(FileContext), PP_FILE, PP_MEM_CATEGORY_SESSION);
232 }
233 
234 /*File properties*/
235 /*Only set the pointer for performance, no deep copy*/
file_name_set(FileContext * context,uint8_t * file_name,uint32_t name_size,bool save_in_context)236 void file_name_set (FileContext *context, uint8_t *file_name, uint32_t name_size,
237         bool save_in_context)
238 {
239     uint8_t *name = file_name;
240     if (!context)
241     {
242         FILE_ERROR("Failed to set file name: no context");
243         return;
244     }
245     if (save_in_context)
246     {
247         if (context->file_name && context->file_name_saved)
248             SnortPreprocFree(context->file_name, sizeof(name_size), PP_FILE, PP_MEM_CATEGORY_SESSION);
249         name = SnortPreprocAlloc(1, name_size, PP_FILE, PP_MEM_CATEGORY_SESSION);
250         memcpy(name, file_name, name_size);
251         context->file_name_saved = true;
252     }
253     context->file_name = name;
254     context->file_name_size = name_size;
255 }
256 
257 /* Return 1: file name available,
258  *        0: file name is unavailable
259  */
260 
file_name_get(FileContext * context,uint8_t ** file_name,uint32_t * name_size)261 int file_name_get (FileContext *context, uint8_t **file_name, uint32_t *name_size)
262 {
263     if (!context)
264     {
265         FILE_ERROR("Failed to fetch file name: no context");
266         return 0;
267     }
268     if (file_name)
269         *file_name = context->file_name;
270     else
271     {
272         FILE_ERROR("Failed to fetch file name: name parameter NULL");
273         return 0;
274     }
275     if (name_size)
276         *name_size = context->file_name_size;
277     else
278     {
279         FILE_ERROR("Failed to fetch file name: size parameter NULL");
280         return 0;
281     }
282     FILE_DEBUG("File name fetched from context: %s, size %d",(char*)(*file_name),*name_size);
283     return 1;
284 }
285 
file_size_set(FileContext * context,uint64_t file_size)286 void file_size_set (FileContext *context, uint64_t file_size)
287 {
288     if (!context)
289     {
290         FILE_ERROR("Failed to set file size: no context");
291         return;
292     }
293     context->file_size = file_size;
294 
295 }
296 
file_size_get(FileContext * context)297 uint64_t file_size_get (FileContext *context)
298 {
299     if (!context)
300     {
301         FILE_ERROR("Failed to fetch file size: no context");
302         return 0;
303     }
304     FILE_DEBUG("File size fetched from context: %d",context->file_size);
305     return (context->file_size);
306 }
307 
file_direction_set(FileContext * context,bool upload)308 void file_direction_set (FileContext *context, bool upload)
309 {
310     if (!context)
311         return;
312     context->upload = upload;
313 
314 }
315 
file_direction_get(FileContext * context)316 bool file_direction_get (FileContext *context)
317 {
318     if (!context)
319         return false;
320     return (context->upload);
321 
322 }
323 
file_sig_sha256_set(FileContext * context,uint8_t * signature)324 void file_sig_sha256_set (FileContext *context, uint8_t * signature)
325 {
326     if (!context)
327         return;
328     context->sha256= signature;
329 }
330 
file_sig_sha256_get(FileContext * context)331 uint8_t* file_sig_sha256_get (FileContext *context)
332 {
333     if (!context)
334         return NULL;
335     return (context->sha256);
336 }
337 
file_type_name(void * conf,uint32_t id)338 char* file_type_name(void* conf, uint32_t id)
339 {
340     RuleInfo *info;
341     if (SNORT_FILE_TYPE_UNKNOWN == id)
342         return ("Unknown file type, done!");
343     else if (SNORT_FILE_TYPE_CONTINUE == id)
344         return ("Undecided file type, continue...");
345     info = file_rule_get(conf, id);
346     if (info != NULL)
347         return info->type;
348     else
349         return NULL;
350 }
351 
file_IDs_from_type(const void * conf,const char * type,uint32_t ** ids,uint32_t * count)352 bool file_IDs_from_type(const void *conf, const char *type,
353      uint32_t **ids, uint32_t *count)
354 {
355     if ( !type )
356         return false;
357 
358     return get_ids_from_type(conf, type, ids, count);
359 }
360 
file_IDs_from_type_version(const void * conf,const char * type,const char * version,uint32_t ** ids,uint32_t * count)361 bool file_IDs_from_type_version(const  void *conf, const char *type,
362     const char *version, uint32_t **ids, uint32_t *count )
363 {
364     if ( !type || !version )
365         return false;
366 
367     return get_ids_from_type_version(conf, type, version, ids, count);
368 }
369 
file_IDs_from_group(const void * conf,const char * group,uint32_t ** ids,uint32_t * count)370 bool file_IDs_from_group(const void *conf, const char *group,
371      uint32_t **ids, uint32_t *count)
372 {
373     if ( !group )
374         return false;
375 
376     return get_ids_from_group(conf, group, ids, count);
377 }
378 
379 #if defined(DEBUG_MSGS) || defined (REG_TEST)
380 /*
381  * Print a 32-byte hash value.
382  */
file_sha256_print(unsigned char * hash)383 void file_sha256_print(unsigned char *hash)
384 {
385     printf("SHA256: %02X%02X %02X%02X %02X%02X %02X%02X "
386             "%02X%02X %02X%02X %02X%02X %02X%02X "
387             "%02X%02X %02X%02X %02X%02X %02X%02X "
388             "%02X%02X %02X%02X %02X%02X %02X%02X\n",
389             hash[0], hash[1], hash[2], hash[3],
390             hash[4], hash[5], hash[6], hash[7],
391             hash[8], hash[9], hash[10], hash[11],
392             hash[12], hash[13], hash[14], hash[15],
393             hash[16], hash[17], hash[18], hash[19],
394             hash[20], hash[21], hash[22], hash[23],
395             hash[24], hash[25], hash[26], hash[27],
396             hash[28], hash[29], hash[30], hash[31]);
397 }
398 #endif
399