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