suricata
util-file.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2020 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18/**
19 * \file
20 *
21 * \author Victor Julien <victor@inliniac.net>
22 * \author Pablo Rincon <pablo.rincon.crespo@gmail.com>
23 *
24 */
25
26#include "suricata-common.h"
27#include "suricata.h"
28#include "flow.h"
29#include "stream.h"
30#include "stream-tcp.h"
31#include "runmodes.h"
32#include "util-hash.h"
33#include "util-debug.h"
34#include "util-memcmp.h"
35#include "util-print.h"
36#include "app-layer-parser.h"
37#include "util-validate.h"
38#include "rust.h"
39
40extern int g_detect_disabled;
41
42/** \brief mask of file flags we'll not set
43 * This mask is set based on global file settings and
44 * cannot be overridden by detection.
45 */
46static uint16_t g_file_flow_mask = 0;
47
48/** \brief switch to force filestore on all files
49 * regardless of the rules.
50 */
51static int g_file_force_filestore = 0;
52
53/** \brief switch to force magic checks on all files
54 * regardless of the rules.
55 */
56static int g_file_force_magic = 0;
57
58/** \brief switch to force md5 calculation on all files
59 * regardless of the rules.
60 */
61static int g_file_force_md5 = 0;
62
63/** \brief switch to force sha1 calculation on all files
64 * regardless of the rules.
65 */
66static int g_file_force_sha1 = 0;
67
68/** \brief switch to force sha256 calculation on all files
69 * regardless of the rules.
70 */
71static int g_file_force_sha256 = 0;
72
73/** \brief switch to force tracking off all files
74 * regardless of the rules.
75 */
76static int g_file_force_tracking = 0;
77
78/** \brief switch to use g_file_store_reassembly_depth
79 * to reassembly files
80 */
81static int g_file_store_enable = 0;
82
83/** \brief stream_config.reassembly_depth equivalent
84 * for files
85 */
86static uint32_t g_file_store_reassembly_depth = 0;
87
88/* prototypes */
89static void FileFree(File *, const StreamingBufferConfig *cfg);
90static void FileEndSha256(File *ff);
91
93{
94 g_file_force_filestore = 1;
95 g_file_flow_mask |= (FLOWFILE_NO_STORE_TS|FLOWFILE_NO_STORE_TC);
96}
97
99{
100 g_file_force_magic = 1;
101 g_file_flow_mask |= (FLOWFILE_NO_MAGIC_TS|FLOWFILE_NO_MAGIC_TC);
102}
103
105{
106 g_file_force_md5 = 1;
107 g_file_flow_mask |= (FLOWFILE_NO_MD5_TS|FLOWFILE_NO_MD5_TC);
108}
109
111{
112 g_file_force_sha1 = 1;
113 g_file_flow_mask |= (FLOWFILE_NO_SHA1_TS|FLOWFILE_NO_SHA1_TC);
114}
115
117{
118 g_file_force_sha256 = 1;
119 g_file_flow_mask |= (FLOWFILE_NO_SHA256_TS|FLOWFILE_NO_SHA256_TC);
120}
121
123{
124 return g_file_force_filestore;
125}
126
127void FileReassemblyDepthEnable(uint32_t size)
128{
129 g_file_store_enable = 1;
130 g_file_store_reassembly_depth = size;
131}
132
134{
135 if (g_file_store_enable == 1)
136 return g_file_store_reassembly_depth;
137 else
139}
140
142{
143 return g_file_force_magic;
144}
145
147{
148 return g_file_force_md5;
149}
150
152{
153 return g_file_force_sha1;
154}
155
157{
158 return g_file_force_sha256;
159}
160
162{
163 g_file_force_tracking = 1;
164 g_file_flow_mask |= (FLOWFILE_NO_SIZE_TS|FLOWFILE_NO_SIZE_TC);
165}
166
167/**
168 * \brief Function to parse forced file hashing configuration.
169 */
171{
172 BUG_ON(conf == NULL);
173
174 SCConfNode *forcehash_node = NULL;
175
176 if (conf != NULL)
177 forcehash_node = SCConfNodeLookupChild(conf, "force-hash");
178
179 if (forcehash_node != NULL) {
180 SCConfNode *field = NULL;
181
182 TAILQ_FOREACH(field, &forcehash_node->head, next) {
183 if (strcasecmp("md5", field->val) == 0) {
184 if (g_disable_hashing) {
185 SCLogInfo("not forcing md5 calculation for logged files: hashing globally "
186 "disabled");
187 } else {
189 SCLogConfig("forcing md5 calculation for logged or stored files");
190 }
191 }
192
193 if (strcasecmp("sha1", field->val) == 0) {
194 if (g_disable_hashing) {
195 SCLogInfo("not forcing sha1 calculation for logged files: hashing globally "
196 "disabled");
197 } else {
199 SCLogConfig("forcing sha1 calculation for logged or stored files");
200 }
201 }
202
203 if (strcasecmp("sha256", field->val) == 0) {
204 if (g_disable_hashing) {
205 SCLogInfo("not forcing sha256 calculation for logged files: hashing globally "
206 "disabled");
207 } else {
209 SCLogConfig("forcing sha256 calculation for logged or stored files");
210 }
211 }
212 }
213 }
214}
215
216uint16_t FileFlowFlagsToFlags(const uint16_t flow_file_flags, uint8_t direction)
217{
218 uint16_t flags = 0;
219
220 if (direction == STREAM_TOSERVER) {
221 if ((flow_file_flags & (FLOWFILE_NO_STORE_TS | FLOWFILE_STORE_TS)) ==
224 } else if (flow_file_flags & FLOWFILE_STORE_TS) {
225 flags |= FILE_STORE;
226 }
227
228 if (flow_file_flags & FLOWFILE_NO_MAGIC_TS) {
230 }
231
232 if (flow_file_flags & FLOWFILE_NO_MD5_TS) {
233 flags |= FILE_NOMD5;
234 }
235
236 if (flow_file_flags & FLOWFILE_NO_SHA1_TS) {
238 }
239
240 if (flow_file_flags & FLOWFILE_NO_SHA256_TS) {
242 }
243 } else {
244 if ((flow_file_flags & (FLOWFILE_NO_STORE_TC | FLOWFILE_STORE_TC)) ==
247 } else if (flow_file_flags & FLOWFILE_STORE_TC) {
248 flags |= FILE_STORE;
249 }
250
251 if (flow_file_flags & FLOWFILE_NO_MAGIC_TC) {
253 }
254
255 if (flow_file_flags & FLOWFILE_NO_MD5_TC) {
256 flags |= FILE_NOMD5;
257 }
258
259 if (flow_file_flags & FLOWFILE_NO_SHA1_TC) {
261 }
262
263 if (flow_file_flags & FLOWFILE_NO_SHA256_TC) {
265 }
266 }
268
269 SCLogDebug("direction %02x flags %02x", direction, flags);
270 return flags;
271}
272
273uint16_t FileFlowToFlags(const Flow *flow, uint8_t direction)
274{
275 return FileFlowFlagsToFlags(flow->file_flags, direction);
276}
277
278void FileApplyTxFlags(const AppLayerTxData *txd, const uint8_t direction, File *file)
279{
280 SCLogDebug("file flags %04x STORE %s NOSTORE %s", file->flags,
281 (file->flags & FILE_STORE) ? "true" : "false",
282 (file->flags & FILE_NOSTORE) ? "true" : "false");
283 uint16_t update_flags = FileFlowFlagsToFlags(txd->file_flags, direction);
286 if (file->flags & FILE_STORE)
287 update_flags &= ~FILE_NOSTORE;
288
289 file->flags |= update_flags;
290 SCLogDebug("file flags %04x STORE %s NOSTORE %s", file->flags,
291 (file->flags & FILE_STORE) ? "true" : "false",
292 (file->flags & FILE_NOSTORE) ? "true" : "false");
295}
296
297static int FileMagicSize(void)
298{
299 /** \todo make this size configurable */
300 return 512;
301}
302
303/**
304 * \brief get the size of the file data
305 *
306 * This doesn't reflect how much of the file we have in memory, just the
307 * total size of filedata so far.
308 */
309uint64_t FileDataSize(const File *file)
310{
311 if (file != NULL && file->sb != NULL) {
312 const uint64_t size = StreamingBufferGetConsecutiveDataRightEdge(file->sb);
313 SCLogDebug("returning %" PRIu64, size);
314 return size;
315 }
316 SCLogDebug("returning 0 (default)");
317 return 0;
318}
319
320/**
321 * \brief get the size of the file
322 *
323 * This doesn't reflect how much of the file we have in memory, just the
324 * total size of file so far.
325 */
326uint64_t FileTrackedSize(const File *file)
327{
328 if (file != NULL) {
329 return file->size;
330 }
331 return 0;
332}
333
334/** \brief test if file is ready to be pruned
335 *
336 * If a file is in the 'CLOSED' state, it means it has been processed
337 * completely by the pipeline in the correct direction. So we can
338 * prune it then.
339 *
340 * For other states, as well as for files we may not need to track
341 * until the close state, more specific checks are done.
342 *
343 * Also does house keeping within the file: move streaming buffer
344 * forward if possible.
345 *
346 * \retval 1 prune (free) this file
347 * \retval 0 file not ready to be freed
348 */
349static int FilePruneFile(File *file, const StreamingBufferConfig *cfg)
350{
351 SCEnter();
352
353 /* file is done when state is closed+, logging/storing is done (if any) */
354 SCLogDebug("file->state %d. Is >= FILE_STATE_CLOSED: %s",
355 file->state, (file->state >= FILE_STATE_CLOSED) ? "yes" : "no");
356 if (file->state >= FILE_STATE_CLOSED) {
357 SCReturnInt(1);
358 }
359
360#ifdef HAVE_MAGIC
361 if (!(file->flags & FILE_NOMAGIC)) {
362 /* need magic but haven't set it yet, bail out */
363 if (file->magic == NULL)
364 SCReturnInt(0);
365 else
366 SCLogDebug("file->magic %s", file->magic);
367 } else {
368 SCLogDebug("file->flags & FILE_NOMAGIC == true");
369 }
370#endif
371 uint64_t left_edge = FileDataSize(file);
372 if (file->flags & FILE_STORE) {
373 left_edge = MIN(left_edge,file->content_stored);
374 }
375
376 if (!g_detect_disabled) {
377 left_edge = MIN(left_edge, file->content_inspected);
378 /* if file has inspect window and min size set, we
379 * do some house keeping here */
380 if (file->inspect_window != 0 && file->inspect_min_size != 0) {
381 const uint64_t file_offset = StreamingBufferGetOffset(file->sb);
382 uint32_t window = file->inspect_window;
383 if (file_offset == 0)
384 window = MAX(window, file->inspect_min_size);
385
386 uint64_t file_size = FileDataSize(file);
387 uint64_t data_size = file_size - file_offset;
388
389 SCLogDebug("window %"PRIu32", file_size %"PRIu64", data_size %"PRIu64,
390 window, file_size, data_size);
391
392 if (data_size > (window * 3)) {
393 file->content_inspected = MAX(file->content_inspected, file->size - window);
394 SCLogDebug("file->content_inspected now %" PRIu64, file->content_inspected);
395 }
396
397 if (left_edge > window)
398 left_edge -= window;
399 else
400 left_edge = 0;
401 }
402 }
403
404 if (left_edge) {
405 SCLogDebug("sliding to %" PRIu64, left_edge);
406 StreamingBufferSlideToOffset(file->sb, cfg, left_edge);
407 }
408
409 SCReturnInt(0);
410}
411
412#ifdef DEBUG
413#define P(file, flag) ((file)->flags & (flag)) ? "true" : "false"
414void FilePrintFlags(const File *file)
415{
416 SCLogDebug("file %p flags %04x "
417 "FILE_TRUNCATED %s "
418 "FILE_NOMAGIC %s "
419 "FILE_NOMD5 %s "
420 "FILE_MD5 %s "
421 "FILE_NOSHA1 %s "
422 "FILE_SHA1 %s "
423 "FILE_NOSHA256 %s "
424 "FILE_SHA256 %s "
425 "FILE_LOGGED %s "
426 "FILE_NOSTORE %s "
427 "FILE_STORE %s "
428 "FILE_STORED %s "
429 "FILE_NOTRACK %s "
430 "FILE_HAS_GAPS %s",
431 file, file->flags, P(file, FILE_TRUNCATED), P(file, FILE_NOMAGIC), P(file, FILE_NOMD5),
432 P(file, FILE_MD5), P(file, FILE_NOSHA1), P(file, FILE_SHA1), P(file, FILE_NOSHA256),
433 P(file, FILE_SHA256), P(file, FILE_LOGGED), P(file, FILE_NOSTORE), P(file, FILE_STORE),
434 P(file, FILE_STORED), P(file, FILE_NOTRACK), P(file, FILE_HAS_GAPS));
435}
436#undef P
437#endif
438
439static void FilePrune(FileContainer *ffc, const StreamingBufferConfig *cfg)
440{
441 SCEnter();
442 SCLogDebug("ffc %p head %p", ffc, ffc->head);
443 File *file = ffc->head;
444 File *prev = NULL;
445
446 while (file) {
447#ifdef DEBUG
448 FilePrintFlags(file);
449#endif
450 if (FilePruneFile(file, cfg) == 0) {
451 prev = file;
452 file = file->next;
453 continue;
454 }
455
456 SCLogDebug("removing file %p", file);
457
458 File *file_next = file->next;
459
460 if (prev)
461 prev->next = file_next;
462 /* update head and tail */
463 if (file == ffc->head)
464 ffc->head = file_next;
465 if (file == ffc->tail)
466 ffc->tail = prev;
467
468 FileFree(file, cfg);
469 file = file_next;
470 }
471 SCReturn;
472}
473
474/**
475 * \brief allocate a FileContainer
476 *
477 * \retval new newly allocated FileContainer
478 * \retval NULL error
479 */
481{
482 FileContainer *new = SCCalloc(1, sizeof(FileContainer));
483 if (unlikely(new == NULL)) {
484 SCLogError("Error allocating mem");
485 return NULL;
486 }
487 new->head = new->tail = NULL;
488 return new;
489}
490
491/**
492 * \brief Recycle a FileContainer
493 *
494 * \param ffc FileContainer
495 */
497{
498 SCLogDebug("ffc %p", ffc);
499 if (ffc == NULL)
500 return;
501
502 File *cur = ffc->head;
503 File *next = NULL;
504 for (;cur != NULL; cur = next) {
505 next = cur->next;
506 FileFree(cur, cfg);
507 }
508 ffc->head = ffc->tail = NULL;
509}
510
511/**
512 * \brief Free a FileContainer
513 *
514 * \param ffc FileContainer
515 */
517{
518 SCLogDebug("ffc %p", ffc);
519 if (ffc == NULL)
520 return;
521
522 File *ptr = ffc->head;
523 File *next = NULL;
524 for (;ptr != NULL; ptr = next) {
525 next = ptr->next;
526 FileFree(ptr, cfg);
527 }
528 ffc->head = ffc->tail = NULL;
529 SCFree(ffc);
530}
531
532/**
533 * \brief Alloc a new File
534 *
535 * \param name character array containing the name (not a string)
536 * \param name_len length in bytes of the name
537 *
538 * \retval new File object or NULL on error
539 */
540static File *FileAlloc(const uint8_t *name, uint16_t name_len)
541{
542 File *new = SCCalloc(1, sizeof(File));
543 if (unlikely(new == NULL)) {
544 SCLogError("Error allocating mem");
545 return NULL;
546 }
547
548 new->name = SCMalloc(name_len);
549 if (new->name == NULL) {
550 SCFree(new);
551 return NULL;
552 }
553
554 new->name_len = name_len;
555 memcpy(new->name, name, name_len);
556
557 new->sid_cnt = 0;
558 new->sid_max = 8;
559 /* SCMalloc() is allowed to fail here because sid well be checked later on */
560 new->sid = SCMalloc(sizeof(uint32_t) * new->sid_max);
561 if (new->sid == NULL)
562 new->sid_max = 0;
563
564 return new;
565}
566
567static void FileFree(File *ff, const StreamingBufferConfig *sbcfg)
568{
569 SCLogDebug("ff %p", ff);
570 if (ff == NULL)
571 return;
572
573 if (ff->name != NULL)
574 SCFree(ff->name);
575 if (ff->sid != NULL)
576 SCFree(ff->sid);
577#ifdef HAVE_MAGIC
578 /* magic returned by libmagic is strdup'd by MagicLookup. */
579 if (ff->magic != NULL)
580 SCFree(ff->magic);
581#endif
582 if (ff->sb != NULL) {
583 StreamingBufferFree(ff->sb, sbcfg);
584 }
585
586 if (ff->md5_ctx)
587 SCMd5Free(ff->md5_ctx);
588 if (ff->sha1_ctx)
589 SCSha1Free(ff->sha1_ctx);
590 if (ff->sha256_ctx)
591 SCSha256Free(ff->sha256_ctx);
592 SCFree(ff);
593}
594
596{
597 SCLogDebug("ffc %p ff %p", ffc, ff);
598 if (ffc->head == NULL || ffc->tail == NULL) {
599 ffc->head = ffc->tail = ff;
600 } else {
601 ffc->tail->next = ff;
602 ffc->tail = ff;
603 }
604}
605
606/**
607 * \brief Tag a file for storing
608 *
609 * \param ff The file to store
610 */
612{
613 SCLogDebug("ff %p", ff);
614 ff->flags |= FILE_STORE;
615 SCReturnInt(0);
616}
617
618/**
619 * \brief check if we have stored enough
620 *
621 * \param ff file
622 *
623 * \retval 0 limit not reached yet
624 * \retval 1 limit reached
625 */
626static int FileStoreNoStoreCheck(File *ff)
627{
628 SCEnter();
629
630 if (ff == NULL) {
631 SCReturnInt(0);
632 }
633
634 if (ff->flags & FILE_NOSTORE) {
635 if (ff->state == FILE_STATE_OPENED &&
636 FileDataSize(ff) >= (uint64_t)FileMagicSize())
637 {
638 SCReturnInt(1);
639 }
640 }
641
642 SCReturnInt(0);
643}
644
645static int AppendData(
646 const StreamingBufferConfig *sbcfg, File *file, const uint8_t *data, uint32_t data_len)
647{
649 data_len > BIT_U32(26)); // 64MiB as a limit per chunk seems already excessive
650
651 SCLogDebug("file %p data_len %u", file, data_len);
652 if (StreamingBufferAppendNoTrack(file->sb, sbcfg, data, data_len) != 0) {
653 SCLogDebug("file %p StreamingBufferAppendNoTrack failed", file);
654 SCReturnInt(-1);
655 }
656
657 if (file->md5_ctx) {
658 SCMd5Update(file->md5_ctx, data, data_len);
659 }
660 if (file->sha1_ctx) {
661 SCSha1Update(file->sha1_ctx, data, data_len);
662 }
663 if (file->sha256_ctx) {
664 SCLogDebug("SHA256 file %p data %p data_len %u", file, data, data_len);
665 SCSha256Update(file->sha256_ctx, data, data_len);
666 } else {
667 SCLogDebug("NO SHA256 file %p data %p data_len %u", file, data, data_len);
668 }
669 SCReturnInt(0);
670}
671
672/** \internal
673 * \brief Flags a file as having gaps
674 *
675 * \param ff the file
676 */
677static void FileFlagGap(File *ff) {
678 ff->flags |= FILE_HAS_GAPS;
681}
682
683/** \internal
684 * \brief Store/handle a chunk of file data in the File structure
685 *
686 * \param ff the file
687 * \param data data chunk
688 * \param data_len data chunk len
689 *
690 * \retval 0 ok
691 * \retval -1 error
692 * \retval -2 no store for this file
693 */
694static int FileAppendDataDo(
695 const StreamingBufferConfig *sbcfg, File *ff, const uint8_t *data, uint32_t data_len)
696{
697 SCEnter();
698#ifdef DEBUG_VALIDATION
699 BUG_ON(ff == NULL);
700#endif
701
702 ff->size += data_len;
703 if (data == NULL) {
704 FileFlagGap(ff);
705 SCReturnInt(0);
706 }
707
708 if (ff->state != FILE_STATE_OPENED) {
709 if (ff->flags & FILE_NOSTORE) {
710 SCReturnInt(-2);
711 }
712 SCReturnInt(-1);
713 }
714
715 if (g_detect_disabled && FileStoreNoStoreCheck(ff) == 1) {
716 int hash_done = 0;
717 /* no storage but forced hashing */
718 if (ff->md5_ctx) {
719 SCMd5Update(ff->md5_ctx, data, data_len);
720 hash_done = 1;
721 }
722 if (ff->sha1_ctx) {
723 SCSha1Update(ff->sha1_ctx, data, data_len);
724 hash_done = 1;
725 }
726 if (ff->sha256_ctx) {
727 SCLogDebug("file %p data %p data_len %u", ff, data, data_len);
728 SCSha256Update(ff->sha256_ctx, data, data_len);
729 hash_done = 1;
730 }
731
732 if (hash_done)
733 SCReturnInt(0);
734
735 if (g_file_force_tracking || (!(ff->flags & FILE_NOTRACK)))
736 SCReturnInt(0);
737
739 SCLogDebug("flowfile state transitioned to FILE_STATE_TRUNCATED");
740 SCReturnInt(-2);
741 }
742
743 SCLogDebug("appending %"PRIu32" bytes", data_len);
744
745 int r = AppendData(sbcfg, ff, data, data_len);
746 if (r != 0) {
748 SCReturnInt(r);
749 }
750
751 SCReturnInt(0);
752}
753
754/**
755 * \brief Store/handle a chunk of file data in the File structure
756 * The last file in the FileContainer will be used.
757 *
758 * \param ffc FileContainer used to append to
759 * \param data data chunk
760 * \param data_len data chunk len
761 *
762 * \retval 0 ok
763 * \retval -1 error
764 * \retval -2 no store for this file
765 */
766int FileAppendData(FileContainer *ffc, const StreamingBufferConfig *sbcfg, const uint8_t *data,
767 uint32_t data_len)
768{
769 SCEnter();
770
771 if (ffc == NULL || ffc->tail == NULL || data_len == 0 || sbcfg == NULL) {
772 SCReturnInt(-1);
773 }
774 int r = FileAppendDataDo(sbcfg, ffc->tail, data, data_len);
775 SCReturnInt(r);
776}
777
778/**
779 * \brief Store/handle a chunk of file data in the File structure
780 * The file with 'track_id' in the FileContainer will be used.
781 *
782 * \param ffc FileContainer used to append to
783 * \param track_id id to lookup the file
784 * \param data data chunk
785 * \param data_len data chunk len
786 *
787 * \retval 0 ok
788 * \retval -1 error
789 * \retval -2 no store for this file
790 */
791int FileAppendDataById(FileContainer *ffc, const StreamingBufferConfig *sbcfg, uint32_t track_id,
792 const uint8_t *data, uint32_t data_len)
793{
794 SCEnter();
795
796 if (ffc == NULL || ffc->tail == NULL || data == NULL || data_len == 0) {
797 SCReturnInt(-1);
798 }
799 File *ff = ffc->head;
800 for ( ; ff != NULL; ff = ff->next) {
801 if (track_id == ff->file_track_id) {
802 int r = FileAppendDataDo(sbcfg, ff, data, data_len);
803 SCReturnInt(r);
804 }
805 }
806 SCReturnInt(-1);
807}
808
809/**
810 * \brief Store/handle a chunk of file data in the File structure
811 * The file with 'track_id' in the FileContainer will be used.
812 *
813 * \param ffc FileContainer used to append to
814 * \param track_id id to lookup the file
815 * \param data data chunk
816 * \param data_len data chunk len
817 *
818 * \retval 0 ok
819 * \retval -1 error
820 * \retval -2 no store for this file
821 */
822int FileAppendGAPById(FileContainer *ffc, const StreamingBufferConfig *sbcfg, uint32_t track_id,
823 const uint8_t *data, uint32_t data_len)
824{
825 SCEnter();
826
827 if (ffc == NULL || ffc->tail == NULL || data == NULL || data_len == 0) {
828 SCReturnInt(-1);
829 }
830 File *ff = ffc->head;
831 for ( ; ff != NULL; ff = ff->next) {
832 if (track_id == ff->file_track_id) {
833 FileFlagGap(ff);
834 SCLogDebug("FILE_HAS_GAPS set");
835
836 int r = FileAppendDataDo(sbcfg, ff, data, data_len);
837 SCReturnInt(r);
838 }
839 }
840 SCReturnInt(-1);
841}
842
843void FileSetInspectSizes(File *file, const uint32_t win, const uint32_t min)
844{
845 file->inspect_window = win;
846 file->inspect_min_size = min;
847}
848
849/**
850 * \brief Sets the offset range for a file.
851 *
852 * \param ffc the container
853 * \param start start offset
854 * \param end end offset
855 *
856 * \retval 0 ok
857 * \retval -1 error
858 */
859int FileSetRange(FileContainer *ffc, uint64_t start, uint64_t end)
860{
861 SCEnter();
862
863 if (ffc == NULL || ffc->tail == NULL) {
864 SCReturnInt(-1);
865 }
866 ffc->tail->start = start;
867 ffc->tail->end = end;
868 SCReturnInt(0);
869}
870
871/**
872 * \brief Open a new File
873 *
874 * \param ffc flow container
875 * \param sbcfg buffer config
876 * \param name filename character array
877 * \param name_len filename len
878 * \param data initial data
879 * \param data_len initial data len
880 * \param flags open flags
881 *
882 * \retval ff flowfile object
883 *
884 * \note filename is not a string, so it's not nul terminated.
885 */
886static File *FileOpenFile(FileContainer *ffc, const StreamingBufferConfig *sbcfg,
887 const uint8_t *name, uint16_t name_len,
888 const uint8_t *data, uint32_t data_len, uint16_t flags)
889{
890 SCEnter();
891
892 //PrintRawDataFp(stdout, name, name_len);
893
894 File *ff = FileAlloc(name, name_len);
895 if (ff == NULL) {
896 SCReturnPtr(NULL, "File");
897 }
898
899 ff->sb = StreamingBufferInit(sbcfg);
900 if (ff->sb == NULL) {
901 FileFree(ff, sbcfg);
902 SCReturnPtr(NULL, "File");
903 }
904 SCLogDebug("ff->sb %p", ff->sb);
905
906 if (flags & FILE_STORE || g_file_force_filestore) {
907 FileStore(ff);
908 } else if (flags & FILE_NOSTORE) {
909 SCLogDebug("not storing this file");
910 ff->flags |= FILE_NOSTORE;
911 }
912 if (flags & FILE_NOMAGIC) {
913 SCLogDebug("not doing magic for this file");
914 ff->flags |= FILE_NOMAGIC;
915 }
916 if (flags & FILE_NOMD5) {
917 SCLogDebug("not doing md5 for this file");
918 ff->flags |= FILE_NOMD5;
919 }
920 if (flags & FILE_NOSHA1) {
921 SCLogDebug("not doing sha1 for this file");
922 ff->flags |= FILE_NOSHA1;
923 }
924 if (flags & FILE_NOSHA256) {
925 SCLogDebug("not doing sha256 for this file");
926 ff->flags |= FILE_NOSHA256;
927 }
928
929 if (!(ff->flags & FILE_NOMD5) || g_file_force_md5) {
930 ff->md5_ctx = SCMd5New();
931 }
932 if (!(ff->flags & FILE_NOSHA1) || g_file_force_sha1) {
933 ff->sha1_ctx = SCSha1New();
934 }
935 if (!(ff->flags & FILE_NOSHA256) || g_file_force_sha256) {
936 ff->sha256_ctx = SCSha256New();
937 SCLogDebug("ff %p ff->sha256_ctx %p", ff, ff->sha256_ctx);
938 }
939
941 SCLogDebug("flowfile state transitioned to FILE_STATE_OPENED");
942
943 ff->fd = -1;
944
945 FileContainerAdd(ffc, ff);
946
947 /* set default window and min inspection size */
949
950 ff->size += data_len;
951 if (data != NULL) {
952 if (AppendData(sbcfg, ff, data, data_len) != 0) {
954 SCReturnPtr(NULL, "File");
955 }
956 SCLogDebug("file size is now %"PRIu64, FileTrackedSize(ff));
957 } else if (data_len > 0) {
958 FileFlagGap(ff);
959 }
960
961 SCReturnPtr(ff, "File");
962}
963
964/**
965 * \retval 0 ok
966 * \retval -1 failed */
968 uint32_t track_id, const uint8_t *name, uint16_t name_len,
969 const uint8_t *data, uint32_t data_len, uint16_t flags)
970{
971 SCLogDebug("ffc %p track_id %u", ffc, track_id);
972 File *ff = FileOpenFile(ffc, sbcfg, name, name_len, data, data_len, flags);
973 if (ff == NULL)
974 return -1;
975
976 ff->file_track_id = track_id;
977 return 0;
978}
979
980int FileCloseFilePtr(File *ff, const StreamingBufferConfig *sbcfg, const uint8_t *data,
981 uint32_t data_len, uint16_t flags)
982{
983 SCEnter();
984
985 if (ff == NULL) {
986 SCReturnInt(-1);
987 }
988
989 if (ff->state != FILE_STATE_OPENED) {
990 SCReturnInt(-1);
991 }
992
993 ff->size += data_len;
994 if (data != NULL) {
995 if (ff->flags & FILE_NOSTORE) {
996 /* no storage but hashing */
997 if (ff->md5_ctx)
998 SCMd5Update(ff->md5_ctx, data, data_len);
999 if (ff->sha1_ctx)
1000 SCSha1Update(ff->sha1_ctx, data, data_len);
1001 if (ff->sha256_ctx) {
1002 SCLogDebug("file %p data %p data_len %u", ff, data, data_len);
1003 SCSha256Update(ff->sha256_ctx, data, data_len);
1004 }
1005 }
1006 if (AppendData(sbcfg, ff, data, data_len) != 0) {
1007 ff->state = FILE_STATE_ERROR;
1008 SCReturnInt(-1);
1009 }
1010 }
1011
1012 if ((flags & FILE_TRUNCATED) || (ff->flags & FILE_HAS_GAPS)) {
1013 SCLogDebug("flags FILE_TRUNCATED %s", (flags & FILE_TRUNCATED) ? "true" : "false");
1014 SCLogDebug("ff->flags FILE_HAS_GAPS %s", (ff->flags & FILE_HAS_GAPS) ? "true" : "false");
1015
1017 SCLogDebug("flowfile state transitioned to FILE_STATE_TRUNCATED");
1018
1019 if (flags & FILE_NOSTORE) {
1020 SCLogDebug("not storing this file");
1021 ff->flags |= FILE_NOSTORE;
1022 } else {
1023 if (g_file_force_sha256 && ff->sha256_ctx) {
1024 SCLogDebug("file %p data %p data_len %u", ff, data, data_len);
1025 FileEndSha256(ff);
1026 }
1027 }
1028 } else {
1030 SCLogDebug("flowfile state transitioned to FILE_STATE_CLOSED");
1031
1032 if (ff->md5_ctx) {
1033 SCMd5Finalize(ff->md5_ctx, ff->md5, sizeof(ff->md5));
1034 ff->md5_ctx = NULL;
1035 ff->flags |= FILE_MD5;
1036 }
1037 if (ff->sha1_ctx) {
1038 SCSha1Finalize(ff->sha1_ctx, ff->sha1, sizeof(ff->sha1));
1039 ff->sha1_ctx = NULL;
1040 ff->flags |= FILE_SHA1;
1041 }
1042 if (ff->sha256_ctx) {
1043 SCLogDebug("file %p data %p data_len %u", ff, data, data_len);
1044 FileEndSha256(ff);
1045 }
1046 }
1047
1048 SCReturnInt(0);
1049}
1050
1051/**
1052 * \brief Close a File
1053 *
1054 * \param ffc the container
1055 * \param data final data if any
1056 * \param data_len data len if any
1057 * \param flags flags
1058 *
1059 * \retval 0 ok
1060 * \retval -1 error
1061 */
1062int FileCloseFile(FileContainer *ffc, const StreamingBufferConfig *sbcfg, const uint8_t *data,
1063 uint32_t data_len, uint16_t flags)
1064{
1065 SCEnter();
1066
1067 if (ffc == NULL || ffc->tail == NULL) {
1068 SCReturnInt(-1);
1069 }
1070
1071 if (FileCloseFilePtr(ffc->tail, sbcfg, data, data_len, flags) == -1) {
1072 SCReturnInt(-1);
1073 }
1074
1075 SCReturnInt(0);
1076}
1077
1078int FileCloseFileById(FileContainer *ffc, const StreamingBufferConfig *sbcfg, uint32_t track_id,
1079 const uint8_t *data, uint32_t data_len, uint16_t flags)
1080{
1081 SCEnter();
1082
1083 if (ffc == NULL || ffc->tail == NULL) {
1084 SCReturnInt(-1);
1085 }
1086
1087 File *ff = ffc->head;
1088 for ( ; ff != NULL; ff = ff->next) {
1089 if (track_id == ff->file_track_id) {
1090 int r = FileCloseFilePtr(ff, sbcfg, data, data_len, flags);
1091 SCReturnInt(r);
1092 }
1093 }
1094 SCReturnInt(-1);
1095}
1096
1097/** \brief set a flow's file flags
1098 * \param set_file_flags flags in both directions that are requested to set
1099 *
1100 * This function will ignore the flags for the irrelevant direction and
1101 * also mask the flags with the global settings.
1102 */
1103void FileUpdateFlowFileFlags(Flow *f, uint16_t set_file_flags, uint8_t direction)
1104{
1105 SCEnter();
1107
1108 /* remove flags not in our direction and
1109 don't disable what is globally enabled */
1110 if (direction == STREAM_TOSERVER) {
1111 set_file_flags &= ~(FLOWFILE_NONE_TC|g_file_flow_mask);
1112 } else {
1113 set_file_flags &= ~(FLOWFILE_NONE_TS|g_file_flow_mask);
1114 }
1115 f->file_flags |= set_file_flags;
1116
1117 SCLogDebug("f->file_flags %04x set_file_flags %04x g_file_flow_mask %04x",
1118 f->file_flags, set_file_flags, g_file_flow_mask);
1119
1120 if (set_file_flags != 0 && f->alproto != ALPROTO_UNKNOWN && f->alstate != NULL) {
1122 if (sd != NULL) {
1123 if ((sd->file_flags & f->file_flags) != f->file_flags) {
1124 SCLogDebug("state data: updating file_flags %04x with flow file_flags %04x",
1125 sd->file_flags, f->file_flags);
1126 sd->file_flags |= f->file_flags;
1127 }
1128 }
1129 }
1130}
1131
1132/**
1133 * \brief disable file storing for files in a transaction
1134 *
1135 * \param f *LOCKED* flow
1136 * \param direction flow direction
1137 * \param tx_id transaction id
1138 */
1139void FileDisableStoringForTransaction(Flow *f, const uint8_t direction, void *tx, uint64_t tx_id)
1140{
1141 if (g_file_force_filestore == 0) {
1143 if (direction & STREAM_TOSERVER) {
1144 txd->file_flags |= FLOWFILE_NO_STORE_TS;
1145 } else {
1146 txd->file_flags |= FLOWFILE_NO_STORE_TC;
1147 }
1148 }
1149}
1150
1151/**
1152 * \brief flag a file with id "file_id" to be stored.
1153 *
1154 * \param fc file store
1155 * \param file_id the file's id
1156 */
1157void FileStoreFileById(FileContainer *fc, uint32_t file_id)
1158{
1159 File *ptr = NULL;
1160
1161 SCEnter();
1162
1163 if (fc != NULL) {
1164 for (ptr = fc->head; ptr != NULL; ptr = ptr->next) {
1165 if (ptr->file_track_id == file_id) {
1166 FileStore(ptr);
1167 }
1168 }
1169 }
1170}
1171
1172static void FileTruncateAllOpenFiles(FileContainer *fc, const StreamingBufferConfig *sbcfg)
1173{
1174 File *ptr = NULL;
1175
1176 SCEnter();
1177
1178 if (fc != NULL) {
1179 for (ptr = fc->head; ptr != NULL; ptr = ptr->next) {
1180 if (ptr->state == FILE_STATE_OPENED) {
1181 FileCloseFilePtr(ptr, sbcfg, NULL, 0, FILE_TRUNCATED);
1182 }
1183 }
1184 }
1185}
1186
1187void FilesPrune(FileContainer *fc, const StreamingBufferConfig *sbcfg, const bool trunc)
1188{
1189 if (trunc) {
1190 FileTruncateAllOpenFiles(fc, sbcfg);
1191 }
1192 FilePrune(fc, sbcfg);
1193}
1194
1195/**
1196 * \brief Finish the SHA256 calculation.
1197 */
1198static void FileEndSha256(File *ff)
1199{
1200 SCLogDebug("ff %p ff->size %" PRIu64, ff, ff->size);
1201 if (!(ff->flags & FILE_SHA256) && ff->sha256_ctx) {
1202 SCSha256Finalize(ff->sha256_ctx, ff->sha256, sizeof(ff->sha256));
1203 ff->sha256_ctx = NULL;
1204 ff->flags |= FILE_SHA256;
1205 }
1206}
struct HtpBodyChunk_ * next
AppLayerTxData * AppLayerParserGetTxData(uint8_t ipproto, AppProto alproto, void *tx)
AppLayerStateData * AppLayerParserGetStateData(uint8_t ipproto, AppProto alproto, void *state)
struct AppLayerTxData AppLayerTxData
struct AppLayerStateData AppLayerStateData
@ ALPROTO_UNKNOWN
#define FILEDATA_CONTENT_INSPECT_MIN_SIZE
#define FILEDATA_CONTENT_INSPECT_WINDOW
SCConfNode * SCConfNodeLookupChild(const SCConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition conf.c:796
uint8_t flags
Definition decode-gre.h:0
TcpStreamCnf stream_config
Definition stream-tcp.c:219
#define FLOWFILE_NO_SIZE_TC
Definition flow.h:150
#define FLOWFILE_NO_STORE_TC
Definition flow.h:135
#define FLOWFILE_NO_SIZE_TS
Definition flow.h:149
#define FLOWFILE_STORE_TS
Definition flow.h:153
#define FLOWFILE_STORE_TC
Definition flow.h:154
#define FLOWFILE_NO_SHA1_TS
Definition flow.h:141
#define FLOWFILE_NONE_TC
Definition flow.h:162
#define FLOWFILE_NO_STORE_TS
Definition flow.h:134
#define FLOWFILE_NO_SHA256_TS
Definition flow.h:145
#define FLOWFILE_NO_SHA256_TC
Definition flow.h:146
#define FLOWFILE_NONE_TS
Definition flow.h:156
#define FLOWFILE_NO_SHA1_TC
Definition flow.h:142
#define FLOWFILE_NO_MD5_TS
Definition flow.h:137
#define FLOWFILE_NO_MAGIC_TS
Definition flow.h:130
#define FLOWFILE_NO_MD5_TC
Definition flow.h:138
#define FLOWFILE_NO_MAGIC_TC
Definition flow.h:131
#define TAILQ_FOREACH(var, head, field)
Definition queue.h:252
uint8_t * name
Definition util-file.h:88
uint32_t inspect_window
Definition util-file.h:103
StreamingBuffer * sb
Definition util-file.h:83
uint64_t size
Definition util-file.h:102
uint8_t md5[SC_MD5_LEN]
Definition util-file.h:94
uint64_t end
Definition util-file.h:106
uint16_t flags
Definition util-file.h:80
FileState state
Definition util-file.h:82
uint8_t sha256[SC_SHA256_LEN]
Definition util-file.h:98
SCMd5 * md5_ctx
Definition util-file.h:93
uint32_t inspect_min_size
Definition util-file.h:104
uint32_t * sid
Definition util-file.h:108
SCSha1 * sha1_ctx
Definition util-file.h:95
int fd
Definition util-file.h:86
struct File_ * next
Definition util-file.h:92
SCSha256 * sha256_ctx
Definition util-file.h:97
uint32_t file_track_id
Definition util-file.h:84
uint8_t sha1[SC_SHA1_LEN]
Definition util-file.h:96
uint64_t content_stored
Definition util-file.h:101
uint64_t content_inspected
Definition util-file.h:99
uint64_t start
Definition util-file.h:105
Flow data structure.
Definition flow.h:356
uint8_t proto
Definition flow.h:378
uint16_t file_flags
Definition flow.h:423
AppProto alproto
application level protocol
Definition flow.h:450
void * alstate
Definition flow.h:479
char * val
Definition conf.h:39
uint32_t reassembly_depth
Definition stream-tcp.h:75
#define BUG_ON(x)
#define MIN(x, y)
#define BIT_U32(n)
#define MAX(x, y)
bool g_disable_hashing
Definition suricata.c:214
const char * name
#define SCEnter(...)
Definition util-debug.h:277
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCReturnInt(x)
Definition util-debug.h:281
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition util-debug.h:225
#define SCReturnPtr(x, type)
Definition util-debug.h:293
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
#define SCLogConfig(...)
Definition util-debug.h:229
#define SCReturn
Definition util-debug.h:279
int FileAppendData(FileContainer *ffc, const StreamingBufferConfig *sbcfg, const uint8_t *data, uint32_t data_len)
Store/handle a chunk of file data in the File structure The last file in the FileContainer will be us...
Definition util-file.c:766
void FilesPrune(FileContainer *fc, const StreamingBufferConfig *sbcfg, const bool trunc)
Definition util-file.c:1187
void FileApplyTxFlags(const AppLayerTxData *txd, const uint8_t direction, File *file)
Definition util-file.c:278
FileContainer * FileContainerAlloc(void)
allocate a FileContainer
Definition util-file.c:480
uint64_t FileDataSize(const File *file)
get the size of the file data
Definition util-file.c:309
uint64_t FileTrackedSize(const File *file)
get the size of the file
Definition util-file.c:326
void FileForceSha256Enable(void)
Definition util-file.c:116
int FileAppendDataById(FileContainer *ffc, const StreamingBufferConfig *sbcfg, uint32_t track_id, const uint8_t *data, uint32_t data_len)
Store/handle a chunk of file data in the File structure The file with 'track_id' in the FileContainer...
Definition util-file.c:791
int FileForceFilestore(void)
Definition util-file.c:122
uint16_t FileFlowFlagsToFlags(const uint16_t flow_file_flags, uint8_t direction)
Definition util-file.c:216
void FileDisableStoringForTransaction(Flow *f, const uint8_t direction, void *tx, uint64_t tx_id)
disable file storing for files in a transaction
Definition util-file.c:1139
void FileContainerRecycle(FileContainer *ffc, const StreamingBufferConfig *cfg)
Recycle a FileContainer.
Definition util-file.c:496
int FileCloseFilePtr(File *ff, const StreamingBufferConfig *sbcfg, const uint8_t *data, uint32_t data_len, uint16_t flags)
Definition util-file.c:980
void FileContainerAdd(FileContainer *ffc, File *ff)
Definition util-file.c:595
int FileAppendGAPById(FileContainer *ffc, const StreamingBufferConfig *sbcfg, uint32_t track_id, const uint8_t *data, uint32_t data_len)
Store/handle a chunk of file data in the File structure The file with 'track_id' in the FileContainer...
Definition util-file.c:822
void FileForceMagicEnable(void)
Definition util-file.c:98
int FileForceSha256(void)
Definition util-file.c:156
int FileCloseFileById(FileContainer *ffc, const StreamingBufferConfig *sbcfg, uint32_t track_id, const uint8_t *data, uint32_t data_len, uint16_t flags)
Definition util-file.c:1078
int FileCloseFile(FileContainer *ffc, const StreamingBufferConfig *sbcfg, const uint8_t *data, uint32_t data_len, uint16_t flags)
Close a File.
Definition util-file.c:1062
void FileSetInspectSizes(File *file, const uint32_t win, const uint32_t min)
Definition util-file.c:843
uint32_t FileReassemblyDepth(void)
Definition util-file.c:133
int FileForceMd5(void)
Definition util-file.c:146
void FileContainerFree(FileContainer *ffc, const StreamingBufferConfig *cfg)
Free a FileContainer.
Definition util-file.c:516
void FileReassemblyDepthEnable(uint32_t size)
Definition util-file.c:127
void FileForceFilestoreEnable(void)
Definition util-file.c:92
int FileForceMagic(void)
Definition util-file.c:141
uint16_t FileFlowToFlags(const Flow *flow, uint8_t direction)
Definition util-file.c:273
int FileSetRange(FileContainer *ffc, uint64_t start, uint64_t end)
Sets the offset range for a file.
Definition util-file.c:859
int FileStore(File *ff)
Tag a file for storing.
Definition util-file.c:611
void FileStoreFileById(FileContainer *fc, uint32_t file_id)
flag a file with id "file_id" to be stored.
Definition util-file.c:1157
void FileForceTrackingEnable(void)
Definition util-file.c:161
int FileOpenFileWithId(FileContainer *ffc, const StreamingBufferConfig *sbcfg, uint32_t track_id, const uint8_t *name, uint16_t name_len, const uint8_t *data, uint32_t data_len, uint16_t flags)
Open a new File.
Definition util-file.c:967
int FileForceSha1(void)
Definition util-file.c:151
void FileForceSha1Enable(void)
Definition util-file.c:110
void FileForceHashParseCfg(SCConfNode *conf)
Function to parse forced file hashing configuration.
Definition util-file.c:170
void FileUpdateFlowFileFlags(Flow *f, uint16_t set_file_flags, uint8_t direction)
set a flow's file flags
Definition util-file.c:1103
void FileForceMd5Enable(void)
Definition util-file.c:104
int g_detect_disabled
Definition suricata.c:186
#define FilePrintFlags(file)
Definition util-file.h:250
#define FILE_HAS_GAPS
Definition util-file.h:59
#define FILE_NOSTORE
Definition util-file.h:54
#define FILE_SHA256
Definition util-file.h:52
#define FILE_MD5
Definition util-file.h:48
#define FILE_LOGGED
Definition util-file.h:53
#define FILE_TRUNCATED
Definition util-file.h:45
#define FILE_NOMAGIC
Definition util-file.h:46
#define FILE_NOMD5
Definition util-file.h:47
#define FILE_NOSHA1
Definition util-file.h:49
#define FILE_NOSHA256
Definition util-file.h:51
#define FILE_STORED
Definition util-file.h:56
@ FILE_STATE_OPENED
Definition util-file.h:70
@ FILE_STATE_TRUNCATED
Definition util-file.h:73
@ FILE_STATE_ERROR
Definition util-file.h:75
@ FILE_STATE_CLOSED
Definition util-file.h:71
#define FILE_STORE
Definition util-file.h:55
#define FILE_SHA1
Definition util-file.h:50
#define FILE_NOTRACK
Definition util-file.h:57
#define SCMalloc(sz)
Definition util-mem.h:47
#define SCFree(p)
Definition util-mem.h:61
#define SCCalloc(nm, sz)
Definition util-mem.h:53
#define unlikely(expr)
StreamingBuffer * StreamingBufferInit(const StreamingBufferConfig *cfg)
void StreamingBufferSlideToOffset(StreamingBuffer *sb, const StreamingBufferConfig *cfg, uint64_t offset)
slide to absolute offset
void StreamingBufferFree(StreamingBuffer *sb, const StreamingBufferConfig *cfg)
int StreamingBufferAppendNoTrack(StreamingBuffer *sb, const StreamingBufferConfig *cfg, const uint8_t *data, uint32_t data_len)
add data w/o tracking a segment
#define DEBUG_VALIDATE_BUG_ON(exp)
#define DEBUG_ASSERT_FLOW_LOCKED(f)