"Fossies" - the Fresh Open Source Software Archive 
Member "snort-2.9.17/src/file-process/file_resume_block.c" (16 Oct 2020, 17694 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_resume_block.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 ** Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved.
3 ** Copyright (C) 2012-2013 Sourcefire, Inc.
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License Version 2 as
7 ** published by the Free Software Foundation. You may not use, modify or
8 ** distribute this program under any other version of the GNU General
9 ** Public License.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 **
20 ** Author(s): Hui Cao <hcao@sourcefire.com>
21 **
22 ** NOTES
23 ** 9.25.2012 - Initial Source Code. Hcao
24 */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include <pthread.h>
31 #include "file_resume_block.h"
32 #include "sf_types.h"
33 #include "file_api.h"
34 #include "snort_bounds.h"
35 #include "ipv6_port.h"
36 #include "sfxhash.h"
37 #include "util.h"
38 #include "decode.h"
39 #include "active.h"
40 #include "sf_sechash.h"
41 #include "file_config.h"
42 #include "file_service.h"
43 #include "file_ss.h"
44 #include "sidechannel.h"
45 #include "file_lib.h"
46
47
48 /* The hash table of expected files */
49 static SFXHASH *fileHash = NULL;
50 extern FileServiceConfig cur_config;
51 extern FileContext* get_main_file_context(void *ssnptr);
52
53 static FileState sig_file_state = { FILE_CAPTURE_SUCCESS, FILE_SIG_DONE };
54 /* this file_cache_mutex is used to synchronize multiple add's to SFXHASH */
55 static pthread_mutex_t file_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
56
57 typedef struct _FileHashKey
58 {
59 struct in6_addr sip;
60 struct in6_addr dip;
61 uint32_t file_sig;
62 } FileHashKey;
63
64 typedef struct _FileNode
65 {
66 time_t expires;
67 File_Verdict verdict;
68 uint32_t file_type_id;
69 uint8_t sha256[SHA256_HASH_SIZE];
70 } FileNode;
71
72 #define MAX_FILES_TRACKED 16384
73
74 void file_resume_block_init(void)
75 {
76 /* number of entries * overhead per entry */
77 unsigned long maxmem = sfxhash_calc_maxmem(MAX_FILES_TRACKED,
78 sizeof(FileHashKey) + sizeof(FileNode));
79
80 fileHash = sfxhash_new(MAX_FILES_TRACKED, sizeof(FileHashKey), sizeof(FileNode),
81 maxmem, 1, NULL, NULL, 1);
82
83 if (!fileHash)
84 FatalError("Failed to create the expected channel hash table.\n");
85 #ifdef SIDE_CHANNEL
86 FileSSConfigInit();
87 #endif
88 }
89
90 void file_resume_block_cleanup(void)
91 {
92 if (fileHash)
93 {
94 pthread_mutex_lock(&file_cache_mutex);
95 sfxhash_delete(fileHash);
96 fileHash = NULL;
97 pthread_mutex_unlock(&file_cache_mutex);
98 }
99 #if defined (SIDE_CHANNEL) && defined (REG_TEST)
100 FileCleanSS();
101 #endif
102 }
103
104 static inline void updateFileNode(FileNode *node, File_Verdict verdict,
105 uint32_t file_type_id, uint8_t *signature)
106 {
107 node->verdict = verdict;
108 node->file_type_id = file_type_id;
109 if (signature)
110 {
111 memcpy(node->sha256, signature, SHA256_HASH_SIZE);
112 }
113 }
114 #ifdef SIDE_CHANNEL
115 static int ProduceSSFileCache(FileHashKey *hk, FileNode *hv)
116 {
117 uint32_t offset = 0;
118
119 void *msg_handle = NULL;
120 void *hdr_ptr = NULL;
121 void *data_ptr = NULL;
122 if (!hk || !hv)
123 {
124 return -1;
125 }
126
127 if (CreateFileSSUpdate(&msg_handle, &hdr_ptr, &data_ptr, SC_MSG_TYPE_FILE_SS_HOST_CACHE, sizeof(*hk) + sizeof(*hv)) != 0)
128 {
129 FILE_ERROR("Side channel: Failed to create side channel update");
130 return -1;
131 }
132
133 if (data_ptr)
134 {
135 memcpy(data_ptr, hk, sizeof(*hk));
136 offset += sizeof(*hk);
137
138 memcpy((uint8_t *)data_ptr + offset, hv, sizeof(*hv));
139 offset += sizeof(*hv);
140
141 SendFileSSUpdate(msg_handle, hdr_ptr, data_ptr, SC_MSG_TYPE_FILE_SS_HOST_CACHE, offset);
142 }
143 #ifdef REG_TEST
144 LogMessage("produce verdict =%d file id =%d \n",hv->verdict,hv->file_type_id);
145 file_sha256_print(hv->sha256);
146 #endif
147 FILE_DEBUG("Side channel: Produce verdict: %d, file id: %d",hv->verdict,hv->file_type_id);
148 return 0;
149 }
150
151 int ConsumeSSFileCache(const uint8_t *buf, uint32_t len)
152 {
153 FileHashKey *hk;
154 FileNode *hv;
155 SFXHASH_NODE *hash_node;
156 FileNode *node;
157
158 if( !buf )
159 {
160 LogMessage("Side channel: No buffer\n");
161 return -1;
162 }
163
164 if( len < sizeof(*hk) + sizeof(*hv) )
165 {
166 LogMessage("Side channel: length too small\n");
167 return -1;
168 }
169 hk = (FileHashKey *)buf;
170 hv = (FileNode *)(buf + sizeof(*hk));
171
172 pthread_mutex_lock(&file_cache_mutex);
173 hash_node = sfxhash_find_node(fileHash, hk);
174 if (hash_node)
175 {
176 if (!(node = hash_node->data))
177 {
178 sfxhash_free_node(fileHash, hash_node);
179 }
180 }
181 else
182 node = NULL;
183
184 if (node)
185 {
186 node->expires = hv->expires ;/* 20 minuts timeout*/
187 updateFileNode(node, hv->verdict, hv->file_type_id, hv->sha256);
188 }
189 else if (sfxhash_add(fileHash, hk, hv) != SFXHASH_OK)
190 {
191 /* Uh, shouldn't get here...
192 * There is already a node or couldn't alloc space
193 * for key. This means bigger problems, but fail
194 * gracefully.
195 */
196 LogMessage("Failed to add file node to hash table\n");
197 pthread_mutex_unlock(&file_cache_mutex);
198 return -1;
199 }
200 pthread_mutex_unlock(&file_cache_mutex);
201 LogMessage("consume verdict =%d file id =%d \n",hv->verdict,hv->file_type_id);
202 #ifdef REG_TEST
203 file_sha256_print(hv->sha256);
204 #endif /* REG_TEST */
205
206 return 0;
207 }
208 #endif
209
210 /** *
211 * @param sip - source IP address
212 * @param dip - destination IP address
213 * @param sport - server sport number
214 * @param file_sig - file signature
215 * @param expiry - session expiry in seconds.
216 */
217 int file_resume_block_add_file(void *pkt, uint32_t file_sig, uint32_t timeout,
218 File_Verdict verdict, uint32_t file_type_id, uint8_t *signature, uint16_t cli_port, uint16_t srv_port, bool create_pinhole, bool direction)
219 {
220 FileHashKey hashKey;
221 SFXHASH_NODE *hash_node = NULL;
222 FileNode *node;
223 FileNode new_node;
224 #ifdef HAVE_DAQ_DP_ADD_DC
225 bool use_other_port = false;
226 #endif
227 sfaddr_t* srcIP;
228 sfaddr_t* dstIP;
229 Packet *p = (Packet*)pkt;
230 time_t now = p->pkth->ts.tv_sec;
231 SAVE_DAQ_PKT_HDR(p);
232
233 srcIP = GET_SRC_IP(p);
234 dstIP = GET_DST_IP(p);
235 sfaddr_copy_to_raw(&hashKey.dip, dstIP);
236 sfaddr_copy_to_raw(&hashKey.sip, srcIP);
237 hashKey.file_sig = file_sig;
238
239 pthread_mutex_lock(&file_cache_mutex);
240 hash_node = sfxhash_find_node(fileHash, &hashKey);
241 if (hash_node)
242 {
243 if (!(node = hash_node->data))
244 {
245 sfxhash_free_node(fileHash, hash_node);
246 }
247 }
248 else
249 node = NULL;
250 pthread_mutex_unlock(&file_cache_mutex);
251
252 if ( timeout == 0 && verdict == 0 && file_type_id == 0)
253 {
254 FileConfig *file_config;
255 FileContext *context;
256 file_config = (FileConfig *)(snort_conf->file_config);
257 context = get_main_file_context(p->ssnptr);
258 if (!context && !node)
259 {
260 FILE_ERROR("Resume block: context and node not found");
261 return -1;
262 }
263 timeout = (uint32_t)file_config->file_block_timeout;
264 if(context)
265 {
266 verdict = context->verdict;
267 file_type_id = context->file_type_id;
268 signature = context->sha256;
269 }
270 else
271 {
272 verdict = node->verdict;
273 file_type_id = node->file_type_id;
274 signature = node->sha256;
275 }
276 #ifdef HAVE_DAQ_DP_ADD_DC
277 use_other_port = true;
278 #endif
279 }
280 #ifdef HAVE_DAQ_DP_ADD_DC
281 if (create_pinhole)
282 {
283 DAQ_DC_Params params;
284
285 memset(¶ms, 0, sizeof(params));
286 params.flags = DAQ_DC_ALLOW_MULTIPLE;
287 params.timeout_ms = 5 * 60 * 1000; /* 5 minutes */
288 if (p->packet_flags & PKT_FROM_CLIENT)
289 {
290 if(use_other_port)
291 {
292 if(direction)
293 DAQ_Add_Dynamic_Protocol_Channel(p, srcIP, 0, dstIP, srv_port, GET_IPH_PROTO(p), ¶ms);
294 else
295 DAQ_Add_Dynamic_Protocol_Channel(p, dstIP, 0, srcIP, srv_port, GET_IPH_PROTO(p), ¶ms);
296 }
297 else
298 DAQ_Add_Dynamic_Protocol_Channel(p, srcIP, 0, dstIP, p->dp, GET_IPH_PROTO(p), ¶ms);
299 FILE_DEBUG("Pinhole created from client packet, direction: %d, time: %d",direction, now);
300 }
301 else if (p->packet_flags & PKT_FROM_SERVER)
302 {
303 if(use_other_port)
304 {
305 if(direction)
306 DAQ_Add_Dynamic_Protocol_Channel(p, srcIP, 0, dstIP, srv_port, GET_IPH_PROTO(p), ¶ms);
307 else
308 DAQ_Add_Dynamic_Protocol_Channel(p, dstIP, 0, srcIP, srv_port, GET_IPH_PROTO(p), ¶ms);
309 }
310 else
311 DAQ_Add_Dynamic_Protocol_Channel(p, dstIP, 0, srcIP, p->sp, GET_IPH_PROTO(p), ¶ms);
312 FILE_DEBUG("Pinhole created from server packet, direction: %d, time: %d",direction, now);
313 }
314 }
315 #endif
316
317 if (node)
318 {
319 FILE_DEBUG("Resume block: Updating file node");
320 node->expires = now + (timeout * 4);/* 20 minuts timeout*/
321 updateFileNode(node, verdict, file_type_id, signature);
322 #ifdef SIDE_CHANNEL
323 if (ProduceSSFileCache(&hashKey, node) < 0)
324 {
325 LogMessage("Failed to add Side channel message\n");
326 }
327 #endif
328 }
329 else
330 {
331
332 FILE_DEBUG("Resume block: Adding file node");
333
334 updateFileNode(&new_node, verdict, file_type_id, signature);
335
336 /*
337 * use the time that we keep files around
338 * since this info would effectively be invalid
339 * after that anyway because the file that
340 * caused this will be gone.
341 */
342 new_node.expires = now + (timeout * 4);/* 20 minuts timeout*/
343
344 /* Add it to the table */
345 #ifdef SIDE_CHANNEL
346 if (ProduceSSFileCache(&hashKey, &new_node) < 0)
347 {
348 LogMessage("Failed to add Side channel message\n");
349 }
350 #endif
351 pthread_mutex_lock(&file_cache_mutex);
352 if (sfxhash_add(fileHash, &hashKey, &new_node) != SFXHASH_OK)
353 {
354 /* Uh, shouldn't get here...
355 * There is already a node or couldn't alloc space
356 * for key. This means bigger problems, but fail
357 * gracefully.
358 */
359 FILE_ERROR("Resume block: Failed to add file node to hash table");
360 pthread_mutex_unlock(&file_cache_mutex);
361 return -1;
362 }
363 pthread_mutex_unlock(&file_cache_mutex);
364 }
365 if (signature)
366 {
367 FILE_DEBUG("Resume block: Added file node with verdict: %d, file signature: %d, hash:"
368 "%02X%02X %02X%02X %02X%02X %02X%02X"
369 "%02X%02X %02X%02X %02X%02X %02X%02X "
370 "%02X%02X %02X%02X %02X%02X %02X%02X "
371 "%02X%02X %02X%02X %02X%02X %02X%02X",
372 verdict, file_sig,
373 signature[0], signature[1], signature[2], signature[3],
374 signature[4], signature[5], signature[6], signature[7],
375 signature[8], signature[9], signature[10], signature[11],
376 signature[12], signature[13], signature[14], signature[15],
377 signature[16], signature[17], signature[18], signature[19],
378 signature[20], signature[21], signature[22], signature[23],
379 signature[24], signature[25], signature[26], signature[27],
380 signature[28], signature[29], signature[30], signature[31]);
381 }
382 else
383 {
384 FILE_DEBUG("Resume block: Added file node with verdict: %d, file signature: %d",
385 verdict, file_sig);
386 }
387 return 0;
388 }
389
390 static inline File_Verdict checkVerdict(Packet *p, FileNode *node, SFXHASH_NODE *hash_node)
391 {
392 File_Verdict verdict = FILE_VERDICT_UNKNOWN;
393 FileContext *context = NULL;
394 bool partialFile = false;
395
396 /*Query the file policy in case verdict has been changed*/
397 /*Check file type first*/
398 if (cur_config.file_type_cb)
399 {
400 verdict = cur_config.file_type_cb(p, p->ssnptr, node->file_type_id, 0,
401 DEFAULT_FILE_ID);
402 FILE_DEBUG("Checking verdict, node verdict: %d, file type verdict: %d",node->verdict, verdict);
403 }
404
405 if ((verdict == FILE_VERDICT_UNKNOWN) ||
406 (verdict == FILE_VERDICT_STOP_CAPTURE))
407 {
408 if (cur_config.file_signature_cb)
409 {
410 context = get_main_file_context(p->ssnptr);
411 if(NULL != context)
412 {
413 partialFile = context->partial_file;
414 }
415 verdict = cur_config.file_signature_cb(p, p->ssnptr, node->sha256, 0,
416 &sig_file_state, 0, DEFAULT_FILE_ID, partialFile );
417 FILE_DEBUG("Checking verdict, node verdict: %d, file signature verdict: %d",node->verdict, verdict);
418 }
419 }
420
421 if ((verdict == FILE_VERDICT_UNKNOWN) ||
422 (verdict == FILE_VERDICT_STOP_CAPTURE))
423 {
424 verdict = node->verdict;
425 }
426
427 if (verdict == FILE_VERDICT_LOG)
428 {
429 pthread_mutex_lock(&file_cache_mutex);
430 sfxhash_free_node(fileHash, hash_node);
431 pthread_mutex_unlock(&file_cache_mutex);
432 if (cur_config.log_file_action)
433 {
434 cur_config.log_file_action(p->ssnptr, FILE_RESUME_LOG);
435 }
436 }
437 else if (verdict == FILE_VERDICT_BLOCK)
438 {
439 Active_ForceDropPacket();
440 Active_DropSession(p);
441 if (cur_config.log_file_action)
442 {
443 cur_config.log_file_action(p->ssnptr, FILE_RESUME_BLOCK);
444 }
445 node->verdict = verdict;
446 }
447 else if (verdict == FILE_VERDICT_REJECT)
448 {
449 Active_ForceDropPacket();
450 Active_DropSession(p);
451 #ifdef ACTIVE_RESPONSE
452 Active_QueueReject();
453 #endif
454 if (cur_config.log_file_action)
455 {
456 cur_config.log_file_action(p->ssnptr, FILE_RESUME_BLOCK);
457 }
458 node->verdict = verdict;
459 }
460 else if (verdict == FILE_VERDICT_PENDING)
461 {
462 /*Take the cached verdict*/
463 Active_ForceDropPacket();
464 Active_DropSession(p);
465 #ifdef ACTIVE_RESPONSE
466 if (FILE_VERDICT_REJECT == node->verdict)
467 Active_QueueReject();
468 #endif
469 if (cur_config.log_file_action)
470 {
471 cur_config.log_file_action(p->ssnptr, FILE_RESUME_BLOCK);
472 }
473 verdict = node->verdict;
474 }
475 FILE_DEBUG("Verdict checked for file node with hash: "
476 "%02X%02X %02X%02X %02X%02X %02X%02X"
477 "%02X%02X %02X%02X %02X%02X %02X%02X "
478 "%02X%02X %02X%02X %02X%02X %02X%02X "
479 "%02X%02X %02X%02X %02X%02X %02X%02X",
480 node->sha256[0], node->sha256[1], node->sha256[2], node->sha256[3],
481 node->sha256[4], node->sha256[5], node->sha256[6], node->sha256[7],
482 node->sha256[8], node->sha256[9], node->sha256[10], node->sha256[11],
483 node->sha256[12], node->sha256[13], node->sha256[14], node->sha256[15],
484 node->sha256[16], node->sha256[17], node->sha256[18], node->sha256[19],
485 node->sha256[20], node->sha256[21], node->sha256[22], node->sha256[23],
486 node->sha256[24], node->sha256[25], node->sha256[26], node->sha256[27],
487 node->sha256[28], node->sha256[29], node->sha256[30], node->sha256[31]);
488
489 return verdict;
490 }
491
492 File_Verdict file_resume_block_check(void *pkt, uint32_t file_sig)
493 {
494 File_Verdict verdict = FILE_VERDICT_UNKNOWN;
495 sfaddr_t* srcIP;
496 sfaddr_t* dstIP;
497 SFXHASH_NODE *hash_node;
498 FileHashKey hashKey;
499 FileNode *node;
500 Packet *p = (Packet*)pkt;
501 SAVE_DAQ_PKT_HDR(pkt);
502
503 /* No hash table, or its empty? Get out of dodge. */
504 if (!fileHash || !sfxhash_count(fileHash))
505 {
506 FILE_DEBUG("No expected sessions");
507 return verdict;
508 }
509
510 srcIP = GET_SRC_IP(p);
511 dstIP = GET_DST_IP(p);
512 sfaddr_copy_to_raw(&hashKey.dip, dstIP);
513 sfaddr_copy_to_raw(&hashKey.sip, srcIP);
514 hashKey.file_sig = file_sig;
515
516 pthread_mutex_lock(&file_cache_mutex);
517 hash_node = sfxhash_find_node(fileHash, &hashKey);
518
519 if (hash_node)
520 {
521 if (!(node = hash_node->data))
522 {
523 sfxhash_free_node(fileHash, hash_node);
524 }
525 }
526 else
527 {
528 pthread_mutex_unlock(&file_cache_mutex);
529 FILE_DEBUG("File not found");
530 return verdict;
531 }
532 pthread_mutex_unlock(&file_cache_mutex);
533
534 if (node)
535 {
536 FILE_DEBUG("Found resumed file");
537 if (node->expires && p->pkth->ts.tv_sec > node->expires)
538 {
539 FILE_DEBUG("File expired, verdict: %d",verdict);
540 pthread_mutex_lock(&file_cache_mutex);
541 sfxhash_free_node(fileHash, hash_node);
542 pthread_mutex_unlock(&file_cache_mutex);
543 return verdict;
544 }
545 /*Query the file policy in case verdict has been changed*/
546 verdict = checkVerdict(p, node, hash_node);
547 }
548 if (verdict == FILE_VERDICT_BLOCK || verdict == FILE_VERDICT_REJECT || verdict == FILE_VERDICT_PENDING)
549 {
550 if (pkt_trace_enabled)
551 addPktTraceData(VERDICT_REASON_FILE, snprintf(trace_line, MAX_TRACE_LINE,
552 "File Process: file not resumed, %s\n", getPktTraceActMsg()));
553 else addPktTraceData(VERDICT_REASON_FILE, 0);
554 FILE_INFO("File not resumed, verdict: %d",verdict);
555 }
556 else
557 FILE_INFO("File resumed, verdict: %d",verdict);
558 return verdict;
559 }